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

(-)a/hudson/manifest.mf (-1 / +1 lines)
Lines 2-6 Link Here
2
OpenIDE-Module: org.netbeans.modules.hudson
2
OpenIDE-Module: org.netbeans.modules.hudson
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/hudson/Bundle.properties
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/hudson/Bundle.properties
4
OpenIDE-Module-Layer: org/netbeans/modules/hudson/layer.xml
4
OpenIDE-Module-Layer: org/netbeans/modules/hudson/layer.xml
5
OpenIDE-Module-Specification-Version: 1.31
5
OpenIDE-Module-Specification-Version: 1.32
6
6
(-)a/hudson/src/org/netbeans/modules/hudson/spi/ProjectHudsonProvider.java (-11 / +130 lines)
Lines 45-50 Link Here
45
package org.netbeans.modules.hudson.spi;
45
package org.netbeans.modules.hudson.spi;
46
46
47
import java.net.URI;
47
import java.net.URI;
48
import java.util.Arrays;
49
import java.util.Collection;
48
import java.util.HashMap;
50
import java.util.HashMap;
49
import java.util.Map;
51
import java.util.Map;
50
import java.util.logging.Level;
52
import java.util.logging.Level;
Lines 54-59 Link Here
54
import org.netbeans.api.annotations.common.CheckForNull;
56
import org.netbeans.api.annotations.common.CheckForNull;
55
import org.netbeans.api.project.Project;
57
import org.netbeans.api.project.Project;
56
import org.netbeans.api.project.ui.OpenProjects;
58
import org.netbeans.api.project.ui.OpenProjects;
59
import org.netbeans.modules.hudson.api.HudsonFolder;
57
import org.netbeans.modules.hudson.api.HudsonInstance;
60
import org.netbeans.modules.hudson.api.HudsonInstance;
58
import org.netbeans.modules.hudson.api.HudsonJob;
61
import org.netbeans.modules.hudson.api.HudsonJob;
59
import org.netbeans.modules.hudson.impl.HudsonManagerImpl;
62
import org.netbeans.modules.hudson.impl.HudsonManagerImpl;
Lines 145-151 Link Here
145
    public static final class Association {
148
    public static final class Association {
146
149
147
        private final String serverURL;
150
        private final String serverURL;
151
        private final String jobURL;
148
        private final String jobName;
152
        private final String jobName;
153
        private final String[] jobPath;
149
154
150
        /**
155
        /**
151
         * Creates an association.
156
         * Creates an association.
Lines 165-171 Link Here
165
                throw new IllegalArgumentException("No slashes permitted in job name: " + jobName);
170
                throw new IllegalArgumentException("No slashes permitted in job name: " + jobName);
166
            }
171
            }
167
            this.serverURL = serverURL;
172
            this.serverURL = serverURL;
173
            this.jobURL = getStandardJobUrl(serverURL, jobName);
168
            this.jobName = jobName;
174
            this.jobName = jobName;
175
            this.jobPath = new String[]{jobName};
176
        }
177
178
        private static String getStandardJobUrl(String serverURL, String jobName) {
179
            return jobName != null
180
                    ? serverURL + "job/" + Utilities.uriEncode(jobName) + "/" // NOI18N
181
                    : serverURL;
182
        }
183
184
        /**
185
         * Creates an association.
186
         *
187
         * @param job URL
188
         * @throws IllegalArgumentException if parameter has invalid syntax
189
         * @since hudson/1.32
190
         */
191
        public Association(String jobURL) throws IllegalArgumentException {
192
            URI.create(jobURL); // check syntax
193
            if (!jobURL.endsWith("/")) { // NOI18N
194
                throw new IllegalArgumentException(jobURL + " must end in a slash"); // NOI18N
195
            }
196
            this.jobURL = jobURL;
197
            this.serverURL = extractServerURL(jobURL);
198
            this.jobPath = extractJobPath(jobURL);
199
            this.jobName = jobPath != null
200
                    ? jobPath[jobPath.length - 1]
201
                    : null;
202
        }
203
204
        private static String extractServerURL(String jobURL) throws IllegalArgumentException {
205
            Matcher m = Pattern.compile("(https?://.+?/)(job/([^/]+)/)*").matcher(jobURL); // NOI18N
206
            if (!m.matches()) {
207
                throw new IllegalArgumentException("Cannot extract server URL: " + jobURL); //NOI18N
208
            } else {
209
                m.group(1);
210
                return m.group(1);
211
            }
212
        }
213
214
        private static String[] extractJobPath(String jobURL) throws IllegalArgumentException {
215
            Matcher m = Pattern.compile("(?:https?://.+?/)(?:[^/]+/)*?((?:job/(?:[^/]+)/)*)").matcher(jobURL); // NOI18N
216
            if (!m.matches()) {
217
                throw new IllegalArgumentException("Cannot extract job path: " + jobURL); //NOI18N
218
            } else {
219
                String rawPath = m.group(1);
220
                if (rawPath == null || rawPath.isEmpty()) {
221
                    return null;
222
                } else {
223
                    String[] elements = rawPath.split("/");
224
                    assert elements.length > 0 && (elements.length % 2) == 0;
225
                    String[] result = new String[elements.length / 2];
226
                    for (int i = 0; i < elements.length; i++) {
227
                        String element = elements[i];
228
                        if (i % 2 == 0) {
229
                            assert "job".equals(element);
230
                        } else {
231
                            String decoded = Utilities.uriDecode(element);
232
                            if (decoded.trim().isEmpty()) {
233
                                throw new IllegalArgumentException("Empty job name: " + jobURL); //NOI18N
234
                            }
235
                            result[i / 2] = decoded;
236
                        }
237
                    }
238
                    return result;
239
                }
240
            }
169
        }
241
        }
170
242
171
        /**
243
        /**
Lines 174-180 Link Here
174
         * @return an association with the same server URL and job name
246
         * @return an association with the same server URL and job name
175
         */
247
         */
176
        public static Association forJob(HudsonJob job) {
248
        public static Association forJob(HudsonJob job) {
177
            return new Association(job.getInstance().getUrl(), job.getName());
249
            return new Association(job.getUrl());
178
        }
250
        }
179
251
180
        /**
252
        /**
Lines 192-210 Link Here
192
        }
264
        }
193
265
194
        /**
266
        /**
267
         * Get copy of job path. Not private - called from tests.
268
         */
269
        String[] getJobPath() {
270
            return Arrays.copyOf(jobPath, jobPath.length);
271
        }
272
273
        /**
195
         * Finds the corresponding job on a registered server, if any.
274
         * Finds the corresponding job on a registered server, if any.
196
         * @return a job with the name {@link #getJobName} on the server with the same {@link #getServerUrl}, or null
275
         * @return a job with the name {@link #getJobName} on the server with the same {@link #getServerUrl}, or null
197
         */
276
         */
198
        public @CheckForNull HudsonJob getJob() {
277
        public @CheckForNull HudsonJob getJob() {
199
            if (jobName == null) {
278
            if (jobPath == null) {
200
                return null;
279
                return null;
201
            }
280
            }
202
            HudsonInstance instance = HudsonManagerImpl.getDefault().getInstance(serverURL);
281
            HudsonInstance instance = HudsonManagerImpl.getDefault().getInstance(serverURL);
203
            if (instance == null) {
282
            if (instance == null) {
204
                return null;
283
                return null;
205
            }
284
            }
206
            for (HudsonJob job : instance.getJobs()) {
285
            if (jobPath.length == 1) {
207
                if (job.getName().equals(jobName)) {
286
                for (HudsonJob job : instance.getJobs()) {
287
                    if (job.getName().equals(jobName)) {
288
                        return job;
289
                    }
290
                }
291
                return null;
292
            } else {
293
                HudsonFolder lastFolder = null;
294
                for (int i = 0; i < jobPath.length; i++) {
295
                    String name = jobPath[i];
296
                    if (i == 0) {
297
                        lastFolder = findFolderByName(instance.getFolders(), name);
298
                    } else if (i < jobPath.length - 1 && lastFolder != null) {
299
                        lastFolder = findFolderByName(lastFolder.getFolders(), name);
300
                    } else if (lastFolder != null) {
301
                        return findJobByName(lastFolder.getJobs(), name);
302
                    }
303
                }
304
            }
305
            return null;
306
        }
307
308
        /**
309
         * Find a folder of specified name in a collection of folders.
310
         *
311
         * @return The folder with name {@code name}, or null if not found.
312
         */
313
        private HudsonFolder findFolderByName(Collection<HudsonFolder> folders,
314
                String name) {
315
            for (HudsonFolder folder : folders) {
316
                if (name.equals(folder.getName())) {
317
                    return folder;
318
                }
319
            }
320
            return null;
321
        }
322
323
        /**
324
         * Find a job of specified name in a collection of jobs.
325
         *
326
         * @return The job with name {@code name}, or null if not found.
327
         */
328
        private HudsonJob findJobByName(Collection<HudsonJob> jobs,
329
                String name) {
330
            for (HudsonJob job : jobs) {
331
                if (name.equals(job.getName())) {
208
                    return job;
332
                    return job;
209
                }
333
                }
210
            }
334
            }
Lines 226-232 Link Here
226
         * URL of either job or server root.
350
         * URL of either job or server root.
227
         */
351
         */
228
        public @Override String toString() {
352
        public @Override String toString() {
229
            return jobName != null ? serverURL + "job/" + Utilities.uriEncode(jobName) + "/" : serverURL; // NOI18N
353
            return jobURL;
230
        }
354
        }
231
355
232
        /**
356
        /**
Lines 234-246 Link Here
234
         * @return an association based on parsing a Hudson job or root URL, or null
358
         * @return an association based on parsing a Hudson job or root URL, or null
235
         */
359
         */
236
        public static Association fromString(String s) {
360
        public static Association fromString(String s) {
237
            Matcher m = Pattern.compile("(https?://.+?/)(?:job/([^/]+)/?)?").matcher(s); // NOI18N
238
            if (!m.matches()) {
239
                return null;
240
            }
241
            String jobNameRaw = m.group(2);
242
            try {
361
            try {
243
                return new Association(m.group(1), jobNameRaw != null ? Utilities.uriDecode(jobNameRaw) : null);
362
                return new Association(s);
244
            } catch (IllegalArgumentException x) {
363
            } catch (IllegalArgumentException x) {
245
                Logger.getLogger(ProjectHudsonProvider.class.getName()).log(Level.WARNING, "Bad URL: {0}", s);
364
                Logger.getLogger(ProjectHudsonProvider.class.getName()).log(Level.WARNING, "Bad URL: {0}", s);
246
                return null;
365
                return null;
(-)a/hudson/test/unit/src/org/netbeans/modules/hudson/spi/ProjectHudsonProviderTest.java (+12 lines)
Lines 76-79 Link Here
76
        assertEquals("Some Job", Association.fromString("http://nowhere.net/hudson/view/someview/job/Some%20Job/").getJobName());
76
        assertEquals("Some Job", Association.fromString("http://nowhere.net/hudson/view/someview/job/Some%20Job/").getJobName());
77
    }
77
    }
78
78
79
    public void testAssociationOfHudsonJobsInFolderHierarchy() {
80
        Association a = Association.fromString(
81
                "http://localhost:8080/app/hudson/job/folder%201/job/folder%201a/job/TestJob/");
82
        assertEquals("http://localhost:8080/app/hudson/", a.getServerUrl());
83
        assertEquals("TestJob", a.getJobName());
84
        String[] expectedPath = {"folder 1", "folder 1a", "TestJob"};
85
        assertEquals("Job path lenght is wrong",
86
                expectedPath.length, a.getJobPath().length);
87
        for (int i = 0; i < expectedPath.length; i++) {
88
            assertEquals(expectedPath[i], a.getJobPath()[i]);
89
        }
90
    }
79
}
91
}

Return to bug 215135