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

(-)projectapi/apichanges.xml (+24 lines)
Lines 76-81 Link Here
76
76
77
    <changes>
77
    <changes>
78
78
79
        <change id="markExternal-for-file-and-URIs">
80
            <api name="general"/>
81
            <summary>The FileOwnerQuery.markExternalOwner allows registration of individal files and URIs</summary>
82
            <version major="1" minor="4"/>
83
            <date day="13" month="5" year="2005"/>
84
            <author login="jlahoda"/>
85
            <compatibility addition="yes" semantic="compatible" binary="compatible">
86
                <p>
87
                    This changes add a new method <code>FileOwnerQuery.markExternalOwner(URI, FileObject, int)</code>,
88
                    and also extends sematics of the existing
89
                    <code>FileOwnerQuery.markExternalOwner(FileObject, FileObject, int)</code> method to allow registration
90
                    of individual files.
91
                </p>
92
            </compatibility>
93
            <description>
94
                <p>
95
                    It is possible to register owner of an individual file using FileOwnerQuery.markExternalOwner.
96
                    It is possible to register owner of a folder or file using URI, so the folder or file does not
97
                    have to exist at the time of registration.
98
                </p>
99
            </description>
100
            <issue number="58313"/>
101
        </change>
102
        
79
        <change id="rel-vers-1">
103
        <change id="rel-vers-1">
80
            <api name="general"/>
104
            <api name="general"/>
81
            <summary>Switched to major release version 1</summary>
105
            <summary>Switched to major release version 1</summary>
(-)projectapi/nbproject/project.properties (+1 lines)
Lines 21-23 Link Here
21
    ${openide/masterfs.dir}/modules/org-netbeans-modules-masterfs.jar:\
21
    ${openide/masterfs.dir}/modules/org-netbeans-modules-masterfs.jar:\
22
    ${core.dir}/core/core.jar:\
22
    ${core.dir}/core/core.jar:\
23
    ${core.dir}/lib/boot.jar
23
    ${core.dir}/lib/boot.jar
24
(-)projectapi/src/org/netbeans/api/project/FileOwnerQuery.java (-7 / +40 lines)
Lines 138-146 Link Here
138
    public static final int EXTERNAL_ALGORITHM_TRANSIENT = 0;
138
    public static final int EXTERNAL_ALGORITHM_TRANSIENT = 0;
139
    
139
    
140
    /**
140
    /**
141
     * Mark an external folder as being owned by a particular project.
141
     * Mark an external folder or file as being owned by a particular project.
142
     * After this call is made, for the duration appropriate to the selected
142
     * After this call is made, for the duration appropriate to the selected
143
     * algorithm, that folder and its ancestors will be considered owned
143
     * algorithm, that folder or file and its ancestors will be considered owned
144
     * by the project (if any) matching the named project directory, except in
144
     * by the project (if any) matching the named project directory, except in
145
     * the case that a lower enclosing project directory can be found.
145
     * the case that a lower enclosing project directory can be found.
146
     * <p class="nonnormative">
146
     * <p class="nonnormative">
Lines 149-163 Link Here
149
     * algorithm is selected, or only when the project is created, if a reliable
149
     * algorithm is selected, or only when the project is created, if a reliable
150
     * persistent algorithm is selected.
150
     * persistent algorithm is selected.
151
     * </p>
151
     * </p>
152
     * @param root a folder which should be considered part of a project
152
     * @param root a folder or a file which should be considered part of a project
153
     * @param owner a project which should be considered to own that folder tree
153
     * @param owner a project which should be considered to own that folder tree
154
     *              (any prior marked external owner is overridden),
154
     *              (any prior marked external owner is overridden),
155
     *              or null to cancel external ownership for this folder root
155
     *              or null to cancel external ownership for this folder root
156
     * @param algorithm an algorithm to use for retaining this information;
156
     * @param algorithm an algorithm to use for retaining this information;
157
     *                  currently may only be {@link #EXTERNAL_ALGORITHM_TRANSIENT}
157
     *                  currently may only be {@link #EXTERNAL_ALGORITHM_TRANSIENT}
158
     * @throws IllegalArgumentException if the root or owner is null, if an unsupported
158
     * @throws IllegalArgumentException if the root or owner is null, if an unsupported
159
     *                                  algorithm is requested, if the root is not a
159
     *                                  algorithm is requested,
160
     *                                  folder, if the root is already a project directory,
160
     *                                  if the root is already a project directory,
161
     *                                  or if the root is already equal to or inside the owner's
161
     *                                  or if the root is already equal to or inside the owner's
162
     *                                  project directory (it may however be an ancestor)
162
     *                                  project directory (it may however be an ancestor)
163
     * @see <a href="@ANT/PROJECT@/org/netbeans/spi/project/support/ant/SourcesHelper.html"><code>SourcesHelper</code></a>
163
     * @see <a href="@ANT/PROJECT@/org/netbeans/spi/project/support/ant/SourcesHelper.html"><code>SourcesHelper</code></a>
Lines 173-180 Link Here
173
        }
173
        }
174
    }
174
    }
175
    
175
    
176
    // XXX may need markExternalOwner(URI root, Project, int)? in case root dir does not exist yet...
176
    /**
177
    // XXX is it useful to mark external owners for individual files?
177
     * Mark an external URI (folder or file) as being owned by a particular project.
178
     * After this call is made, for the duration appropriate to the selected
179
     * algorithm, that folder or file and its ancestors will be considered owned
180
     * by the project (if any) matching the named project directory, except in
181
     * the case that a lower enclosing project directory can be found.
182
     * <p class="nonnormative">
183
     * Typical usage would be to call this method for each external source root
184
     * of a project (if any) as soon as the project is loaded, if a transient
185
     * algorithm is selected, or only when the project is created, if a reliable
186
     * persistent algorithm is selected.
187
     * </p>
188
     * @param root an URI of a folder or a file which should be considered part of a project
189
     * @param owner a project which should be considered to own that folder tree
190
     *              (any prior marked external owner is overridden),
191
     *              or null to cancel external ownership for this folder root
192
     * @param algorithm an algorithm to use for retaining this information;
193
     *                  currently may only be {@link #EXTERNAL_ALGORITHM_TRANSIENT}
194
     * @throws IllegalArgumentException if the root or owner is null, if an unsupported
195
     *                                  algorithm is requested,
196
     *                                  if the root is already a project directory,
197
     *                                  or if the root is already equal to or inside the owner's
198
     *                                  project directory (it may however be an ancestor)
199
     * @see <a href="@ANT/PROJECT@/org/netbeans/spi/project/support/ant/SourcesHelper.html"><code>SourcesHelper</code></a>
200
     */
201
    public static void markExternalOwner(URI root, Project owner, int algorithm) throws IllegalArgumentException {
202
        switch (algorithm) {
203
        case EXTERNAL_ALGORITHM_TRANSIENT:
204
            // XXX check args
205
            SimpleFileOwnerQueryImplementation.markExternalOwnerTransient(root, owner);
206
            break;
207
        default:
208
            throw new IllegalArgumentException("No such algorithm: " + algorithm); // NOI18N
209
        }
210
    }
178
    
211
    
179
    /* TBD whether this is necessary:
212
    /* TBD whether this is necessary:
180
    public static FileObject getMarkedExternalOwner(FileObject root) {}
213
    public static FileObject getMarkedExternalOwner(FileObject root) {}
(-)projectapi/src/org/netbeans/modules/projectapi/SimpleFileOwnerQueryImplementation.java (-22 / +55 lines)
Lines 14-24 Link Here
14
package org.netbeans.modules.projectapi;
14
package org.netbeans.modules.projectapi;
15
15
16
import java.io.IOException;
16
import java.io.IOException;
17
import java.lang.ref.WeakReference;
17
import java.net.MalformedURLException;
18
import java.net.MalformedURLException;
18
import java.net.URI;
19
import java.net.URI;
19
import java.net.URISyntaxException;
20
import java.net.URISyntaxException;
20
import java.net.URL;
21
import java.net.URL;
21
import java.util.Collections;
22
import java.util.Collections;
23
import java.util.HashMap;
22
import java.util.Map;
24
import java.util.Map;
23
import java.util.WeakHashMap;
25
import java.util.WeakHashMap;
24
import org.netbeans.api.project.Project;
26
import org.netbeans.api.project.Project;
Lines 54-84 Link Here
54
    }
56
    }
55
        
57
        
56
    public Project getOwner(FileObject f) {
58
    public Project getOwner(FileObject f) {
57
        if (f.isData()) {
58
            f = f.getParent();
59
        }
60
        while (f != null) {
59
        while (f != null) {
61
            Project p;
60
            if (f.isFolder()) {
62
            try {
61
                Project p;
63
                p = ProjectManager.getDefault().findProject(f);
64
            } catch (IOException e) {
65
                // There is a project here, but we cannot load it...
66
                ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
67
                return null;
68
            }
69
            if (p != null) {
70
                return p;
71
            }
72
            FileObject externalOwner = (FileObject)externalOwners.get(f);
73
            if (externalOwner != null) {
74
                try {
62
                try {
75
                    // Note: will be null if there is no such project.
63
                    p = ProjectManager.getDefault().findProject(f);
76
                    return ProjectManager.getDefault().findProject(externalOwner);
77
                } catch (IOException e) {
64
                } catch (IOException e) {
78
                    // There is a project there, but we cannot load it...
65
                    // There is a project here, but we cannot load it...
79
                    ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
66
                    ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
80
                    return null;
67
                    return null;
81
                }
68
                }
69
                if (p != null) {
70
                    return p;
71
                }
72
            }
73
            
74
            WeakReference/*<FileObject>*/ externalOwnersReference =
75
                    (WeakReference/*<FileObject>*/) externalOwners.get(fileObject2URI(f));
76
            
77
            if (externalOwnersReference != null) {
78
                FileObject externalOwner = (FileObject) externalOwnersReference.get();
79
                
80
                if (externalOwner != null) {
81
                    try {
82
                        // Note: will be null if there is no such project.
83
                        return ProjectManager.getDefault().findProject(externalOwner);
84
                    } catch (IOException e) {
85
                        // There is a project there, but we cannot load it...
86
                        ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
87
                        return null;
88
                    }
89
                }
82
            }
90
            }
83
            f = f.getParent();
91
            f = f.getParent();
84
        }
92
        }
Lines 88-94 Link Here
88
    /**
96
    /**
89
     * Map from external source roots to the owning project directories.
97
     * Map from external source roots to the owning project directories.
90
     */
98
     */
91
    private static final Map/*<FileObject,FileObject>*/ externalOwners =
99
    private static final Map/*<URI,WeakReference<FileObject>>*/ externalOwners =
100
        Collections.synchronizedMap(new WeakHashMap());
101
    private static final Map/*<FileObject, URI>*/ project2External =
92
        Collections.synchronizedMap(new WeakHashMap());
102
        Collections.synchronizedMap(new WeakHashMap());
93
    
103
    
94
    /** @see FileOwnerQuery#reset */
104
    /** @see FileOwnerQuery#reset */
Lines 96-107 Link Here
96
        externalOwners.clear();
106
        externalOwners.clear();
97
    }
107
    }
98
    
108
    
109
    private static URI fileObject2URI(FileObject f) {
110
        try {
111
            return new URI(f.getURL().toString());
112
        } catch (Exception e) {
113
            e.printStackTrace();
114
            return null;
115
        }
116
    }
117
    
99
    /** @see FileOwnerQuery#markExternalOwner */
118
    /** @see FileOwnerQuery#markExternalOwner */
100
    public static void markExternalOwnerTransient(FileObject root, Project owner) {
119
    public static void markExternalOwnerTransient(FileObject root, Project owner) {
120
        markExternalOwnerTransient(fileObject2URI(root), owner);
121
    }
122
    
123
    /** @see FileOwnerQuery#markExternalOwner */
124
    public static void markExternalOwnerTransient(URI root, Project owner) {
101
        if (owner != null) {
125
        if (owner != null) {
102
            externalOwners.put(root, owner.getProjectDirectory());
126
            externalOwners.put(root, new WeakReference(owner.getProjectDirectory()));
127
            project2External.put(owner.getProjectDirectory(), root);
103
        } else {
128
        } else {
104
            externalOwners.remove(root);
129
            WeakReference/*<FileObject>*/ ownerReference = (WeakReference/*<FileObject>*/) externalOwners.remove(root);
130
            
131
            if (ownerReference != null) {
132
                FileObject ownerFO = (FileObject) ownerReference.get();
133
                
134
                if (ownerFO != null) {
135
                    project2External.remove(ownerFO);
136
                }
137
            }
105
        }
138
        }
106
    }
139
    }
107
    
140
    
(-)projectapi/test/unit/src/org/netbeans/api/project/FileOwnerQueryTest.java (-2 / +127 lines)
Lines 12-19 Link Here
12
 */
12
 */
13
13
14
package org.netbeans.api.project;
14
package org.netbeans.api.project;
15
16
import java.io.OutputStream;
15
import java.io.OutputStream;
16
import java.lang.ref.WeakReference;
17
import java.net.URI;
17
import java.net.URI;
18
import java.util.zip.CRC32;
18
import java.util.zip.CRC32;
19
import java.util.zip.ZipEntry;
19
import java.util.zip.ZipEntry;
Lines 22-28 Link Here
22
import org.openide.filesystems.FileLock;
22
import org.openide.filesystems.FileLock;
23
import org.openide.filesystems.FileObject;
23
import org.openide.filesystems.FileObject;
24
import org.openide.filesystems.FileUtil;
24
import org.openide.filesystems.FileUtil;
25
import org.openide.util.Lookup;
26
25
27
/**
26
/**
28
 * Test functionality of FileOwnerQuery.
27
 * Test functionality of FileOwnerQuery.
Lines 156-161 Link Here
156
        assertEquals("but subprojects are not part of it", ProjectManager.getDefault().findProject(ext3subproj), p3);
155
        assertEquals("but subprojects are not part of it", ProjectManager.getDefault().findProject(ext3subproj), p3);
157
        FileOwnerQuery.markExternalOwner(ext3, null, FileOwnerQuery.EXTERNAL_ALGORITHM_TRANSIENT);
156
        FileOwnerQuery.markExternalOwner(ext3, null, FileOwnerQuery.EXTERNAL_ALGORITHM_TRANSIENT);
158
        assertEquals("unmarking an owner works", null, FileOwnerQuery.getOwner(ext3));
157
        assertEquals("unmarking an owner works", null, FileOwnerQuery.getOwner(ext3));
158
    }
159
160
    public void testExternalOwnerFile() throws Exception {
161
        FileObject ext1 = scratch.getFileObject("external1");
162
        FileObject extfile1 = ext1.getFileObject("subdir/file");
163
        assertEquals("no owner yet", null, FileOwnerQuery.getOwner(extfile1));
164
        FileOwnerQuery.markExternalOwner(extfile1, p, FileOwnerQuery.EXTERNAL_ALGORITHM_TRANSIENT);
165
        assertEquals("now have an owner", p, FileOwnerQuery.getOwner(extfile1));
166
        assertEquals("not for the projdir", null, FileOwnerQuery.getOwner(ext1));
167
        assertEquals("and not for something else", null, FileOwnerQuery.getOwner(scratch));
168
        FileObject ext2 = scratch.getFileObject("external2");
169
        FileObject extfile2 = ext2.getFileObject("subdir/file");
170
        assertEquals("no owner yet", null, FileOwnerQuery.getOwner(extfile2));
171
        Project p2 = ProjectManager.getDefault().findProject(subprojdir);
172
        FileOwnerQuery.markExternalOwner(extfile2, p2, FileOwnerQuery.EXTERNAL_ALGORITHM_TRANSIENT);
173
        assertEquals("now have an owner", p2, FileOwnerQuery.getOwner(extfile2));
174
        assertEquals("not for the projdir", null, FileOwnerQuery.getOwner(ext2));
175
        assertEquals("and not for something else", null, FileOwnerQuery.getOwner(scratch));
176
        assertEquals("still correct for first proj", p, FileOwnerQuery.getOwner(extfile1));
177
        
178
        //XXX: unmarking files.
179
    }
180
    
181
    public void testExternalOwnerURI() throws Exception {
182
        FileObject ext1 = scratch.getFileObject("external1");
183
        FileObject extfile1 = ext1.getFileObject("subdir/file");
184
        assertEquals("no owner yet through FileObjects", null, FileOwnerQuery.getOwner(extfile1));
185
        assertEquals("no owner yet through URI", null, FileOwnerQuery.getOwner(extfile1));
186
        FileOwnerQuery.markExternalOwner(fileObject2URI(ext1), p, FileOwnerQuery.EXTERNAL_ALGORITHM_TRANSIENT);
187
        assertEquals("now have an owner through FileObjects", p, FileOwnerQuery.getOwner(extfile1));
188
        assertEquals("now have an owner through URI", p, FileOwnerQuery.getOwner(fileObject2URI(extfile1)));
189
        assertEquals("even for the projdir throught FileObjects", p, FileOwnerQuery.getOwner(ext1));
190
        assertEquals("even for the projdir throught URI", p, FileOwnerQuery.getOwner(fileObject2URI(ext1)));
191
        assertEquals("but not for something else throught FileObjects", null, FileOwnerQuery.getOwner(scratch));
192
        assertEquals("but not for something else throught URI", null, FileOwnerQuery.getOwner(fileObject2URI(scratch)));
193
        FileObject ext2 = scratch.getFileObject("external2");
194
        FileObject extfile2 = ext2.getFileObject("subdir/file");
195
        assertEquals("no owner yet through FileObjects", null, FileOwnerQuery.getOwner(extfile2));
196
        assertEquals("no owner yet through URI", null, FileOwnerQuery.getOwner(fileObject2URI(extfile2)));
197
        Project p2 = ProjectManager.getDefault().findProject(subprojdir);
198
        FileOwnerQuery.markExternalOwner(fileObject2URI(ext2), p2, FileOwnerQuery.EXTERNAL_ALGORITHM_TRANSIENT);
199
        assertEquals("now have an owner through FileObjects", p2, FileOwnerQuery.getOwner(extfile2));
200
        assertEquals("now have an owner through URI", p2, FileOwnerQuery.getOwner(fileObject2URI(extfile2)));
201
        assertEquals("even for the projdir through FileObjects", p2, FileOwnerQuery.getOwner(ext2));
202
        assertEquals("even for the projdir through URI", p2, FileOwnerQuery.getOwner(ext2));
203
        assertEquals("but not for something else through FileObjects", null, FileOwnerQuery.getOwner(scratch));
204
        assertEquals("but not for something else through URI", null, FileOwnerQuery.getOwner(fileObject2URI(scratch)));
205
        assertEquals("still correct for first proj through FileObjects", p, FileOwnerQuery.getOwner(extfile1));
206
        assertEquals("still correct for first proj through URI", p, FileOwnerQuery.getOwner(fileObject2URI(extfile1)));
207
        FileObject ext3 = scratch.getFileObject("external3");
208
        assertEquals("no owner yet through FileObjects", null, FileOwnerQuery.getOwner(ext3));
209
        assertEquals("no owner yet through URI", null, FileOwnerQuery.getOwner(fileObject2URI(ext3)));
210
        FileOwnerQuery.markExternalOwner(fileObject2URI(ext3), p, FileOwnerQuery.EXTERNAL_ALGORITHM_TRANSIENT);
211
        assertEquals("now have an owner through FileObjects", p, FileOwnerQuery.getOwner(ext3));
212
        assertEquals("now have an owner through URI", p, FileOwnerQuery.getOwner(fileObject2URI(ext3)));
213
        FileObject ext3subproj = ext3.getFileObject("subproject");
214
        Project p3 = FileOwnerQuery.getOwner(ext3subproj);
215
        assertNotSame("different project", p, p3);
216
        assertEquals("but subprojects are not part of it", ProjectManager.getDefault().findProject(ext3subproj), p3);
217
        FileOwnerQuery.markExternalOwner(fileObject2URI(ext3), null, FileOwnerQuery.EXTERNAL_ALGORITHM_TRANSIENT);
218
        assertEquals("unmarking an owner works through FileObjects", null, FileOwnerQuery.getOwner(ext3));
219
        assertEquals("unmarking an owner works through URI", null, FileOwnerQuery.getOwner(fileObject2URI(ext3)));
220
    }
221
    
222
    public void testExternalOwnerFileURI() throws Exception {
223
        FileObject ext1 = scratch.getFileObject("external1");
224
        FileObject extfile1 = ext1.getFileObject("subdir/file");
225
        assertEquals("no owner yet through FileObjects", null, FileOwnerQuery.getOwner(extfile1));
226
        assertEquals("no owner yet through URI", null, FileOwnerQuery.getOwner(fileObject2URI(extfile1)));
227
        FileOwnerQuery.markExternalOwner(fileObject2URI(extfile1), p, FileOwnerQuery.EXTERNAL_ALGORITHM_TRANSIENT);
228
        assertEquals("now have an owner through FileObjects", p, FileOwnerQuery.getOwner(extfile1));
229
        assertEquals("now have an owner through URI", p, FileOwnerQuery.getOwner(fileObject2URI(extfile1)));
230
        assertEquals("not for the projdir through FileObjects", null, FileOwnerQuery.getOwner(ext1));
231
        assertEquals("not for the projdir through URI", null, FileOwnerQuery.getOwner(fileObject2URI(ext1)));
232
        assertEquals("and not for something else through FileObjects", null, FileOwnerQuery.getOwner(scratch));
233
        assertEquals("and not for something else through URI", null, FileOwnerQuery.getOwner(fileObject2URI(scratch)));
234
        FileObject ext2 = scratch.getFileObject("external2");
235
        FileObject extfile2 = ext2.getFileObject("subdir/file");
236
        assertEquals("no owner yet through FileObjects", null, FileOwnerQuery.getOwner(extfile2));
237
        assertEquals("no owner yet through URI", null, FileOwnerQuery.getOwner(fileObject2URI(extfile2)));
238
        Project p2 = ProjectManager.getDefault().findProject(subprojdir);
239
        FileOwnerQuery.markExternalOwner(fileObject2URI(extfile2), p2, FileOwnerQuery.EXTERNAL_ALGORITHM_TRANSIENT);
240
        assertEquals("now have an owner through FileObjects", p2, FileOwnerQuery.getOwner(extfile2));
241
        assertEquals("now have an owner through URI", p2, FileOwnerQuery.getOwner(fileObject2URI(extfile2)));
242
        assertEquals("not for the projdir through FileObjects", null, FileOwnerQuery.getOwner(ext2));
243
        assertEquals("not for the projdir through URI", null, FileOwnerQuery.getOwner(fileObject2URI(ext2)));
244
        assertEquals("and not for something else through FileObjects", null, FileOwnerQuery.getOwner(scratch));
245
        assertEquals("and not for something else through URI", null, FileOwnerQuery.getOwner(fileObject2URI(scratch)));
246
        assertEquals("still correct for first proj through FileObjects", p, FileOwnerQuery.getOwner(extfile1));
247
        assertEquals("still correct for first proj through URI", p, FileOwnerQuery.getOwner(fileObject2URI(extfile1)));
248
        
249
        //XXX: unmarking files.
250
    }
251
    
252
    public void testIsProjectDirCollectable() throws Exception {
253
        Project p2 = ProjectManager.getDefault().findProject(subprojdir);
254
        FileObject root = p2.getProjectDirectory();
255
        FileObject ext2 = scratch.getFileObject("external2");
256
        FileObject extfile2 = ext2.getFileObject("subdir/file");
257
        
258
        FileOwnerQuery.markExternalOwner(fileObject2URI(extfile2), p2, FileOwnerQuery.EXTERNAL_ALGORITHM_TRANSIENT);
259
        
260
        WeakReference p2WR = new WeakReference(p2);
261
        WeakReference rootWR = new WeakReference(root);
262
        
263
        p2 = null;
264
        root = null;
265
        ext2 = null;
266
        extfile2 = null;
267
        subprojdir = null;
268
        subprojfile = null;
269
        
270
        //there are timed references holding the project, let them time-out.
271
        Thread.sleep(30000);
272
        
273
        assertGC("project 2 collected", p2WR);
274
        assertGC("project 2's project dir collected", rootWR);
275
    }
276
    
277
    private static URI fileObject2URI(FileObject f) {
278
        try {
279
            return new URI(f.getURL().toString());
280
        } catch (Exception e) {
281
            e.printStackTrace();
282
            return null;
283
        }
159
    }
284
    }
160
    
285
    
161
    // XXX test URI usage of external owner
286
    // XXX test URI usage of external owner

Return to bug 58313