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

(-)openide/modules/src/org/openide/modules/Dependency.java (-132 / +124 lines)
Lines 19-30 Link Here
19
19
20
package org.openide.modules;
20
package org.openide.modules;
21
21
22
import java.util.Arrays;
22
import java.util.Collections;
23
import java.util.Collections;
23
import java.util.HashMap;
24
import java.util.HashMap;
24
import java.util.HashSet;
25
import java.util.HashSet;
25
import java.util.Map;
26
import java.util.Map;
26
import java.util.Set;
27
import java.util.Set;
27
import java.util.StringTokenizer;
28
import java.util.StringTokenizer;
29
import java.util.TreeSet;
30
import org.openide.util.Exceptions;
28
import org.openide.util.Utilities;
31
import org.openide.util.Utilities;
29
32
30
/** A dependency a module can have.
33
/** A dependency a module can have.
Lines 121-131 Link Here
121
        this.version = (version != null) ? version.intern() : null;
124
        this.version = (version != null) ? version.intern() : null;
122
    }
125
    }
123
126
127
    private static void checkCodeName(String codeName, boolean slashOK) throws IllegalArgumentException {
128
        //This shows up as a hot spot during startup;  it should be reasonable
129
        //enough to disable it when assertions are off.
130
        try {
131
            String msg;
132
            assert (msg = validCodeName(codeName, slashOK)) == null : msg;
133
        } catch (AssertionError e) {
134
            Exceptions.printStackTrace (e);
135
            //Compatibility
136
            throw new IllegalArgumentException(e.getMessage());
137
        }
138
    }
139
    
124
    /** Verify the format of a code name.
140
    /** Verify the format of a code name.
125
     * Caller specifies whether a slash plus release version is permitted in this context.
141
     * Caller specifies whether a slash plus release version is permitted in this context.
126
     */
142
     */
127
    private static void checkCodeName(String codeName, boolean slashOK)
143
    private static String validCodeName(String codeName, boolean slashOK) {
128
    throws IllegalArgumentException {
129
        String base;
144
        String base;
130
        int slash = codeName.indexOf('/'); // NOI18N
145
        int slash = codeName.indexOf('/'); // NOI18N
131
146
Lines 133-139 Link Here
133
            base = codeName;
148
            base = codeName;
134
        } else {
149
        } else {
135
            if (!slashOK) {
150
            if (!slashOK) {
136
                throw new IllegalArgumentException("No slash permitted in: " + codeName); // NOI18N
151
                return "No slash permitted in: " + codeName; // NOI18N
137
            }
152
            }
138
153
139
            base = codeName.substring(0, slash);
154
            base = codeName.substring(0, slash);
Lines 146-196 Link Here
146
                    int release = Integer.parseInt(rest);
161
                    int release = Integer.parseInt(rest);
147
162
148
                    if (release < 0) {
163
                    if (release < 0) {
149
                        throw new IllegalArgumentException("Negative release number: " + codeName); // NOI18N
164
                        return "Negative release number: " + codeName; // NOI18N
150
                    }
165
                    }
151
                } else {
166
                } else {
152
                    int release = Integer.parseInt(rest.substring(0, dash));
167
                    int release = Integer.parseInt(rest.substring(0, dash));
153
                    int releaseMax = Integer.parseInt(rest.substring(dash + 1));
168
                    int releaseMax = Integer.parseInt(rest.substring(dash + 1));
154
169
155
                    if (release < 0) {
170
                    if (release < 0) {
156
                        throw new IllegalArgumentException("Negative release number: " + codeName); // NOI18N
171
                        return "Negative release number: " + codeName; // NOI18N
157
                    }
172
                    }
158
173
159
                    if (releaseMax <= release) {
174
                    if (releaseMax <= release) {
160
                        throw new IllegalArgumentException("Release number range must be increasing: " + codeName); // NOI18N
175
                        return "Release number range must be increasing: " + codeName; // NOI18N
161
                    }
176
                    }
162
                }
177
                }
163
            } catch (NumberFormatException e) {
178
            } catch (NumberFormatException e) {
164
                throw new IllegalArgumentException(e.toString());
179
                return e.toString();
165
            }
180
            }
166
        }
181
        }
167
182
168
        // Now check that the rest is a valid package.
183
        // Now check that the rest is a valid package.
169
        StringTokenizer tok = new StringTokenizer(base, ".", true); // NOI18N
184
        String[] parts = base.split ("\\.");
170
185
171
        if ((tok.countTokens() % 2) == 0) {
186
        //No idea what this test was doing in the original code, but
172
            throw new NumberFormatException("Even number of pieces: " + base); // NOI18N
187
        //it certainly seems wrong
173
        }
188
//        if ((parts.length % 2) == 0) {
189
//            return "Even number of pieces: " + base; // NOI18N
190
//        }
174
191
175
        boolean expectingPath = true;
192
        for (String s : parts) {
176
193
            if (!Utilities.isJavaIdentifier(s) &&  !"enum".equals (s)) { // NOI18N
177
        while (tok.hasMoreTokens()) {
194
                return "Bad package component in " + base + " - not a " +
178
            if (expectingPath) {
195
                       "java identifier: " + s; // NOI18N
179
                expectingPath = false;
180
181
                String nt = tok.nextToken();
182
                if (!Utilities.isJavaIdentifier(nt) &&  !"enum".equals (nt)) { // NOI18N
183
                    throw new IllegalArgumentException("Bad package component in " + base); // NOI18N
184
                }
196
                }
185
            } else {
186
                if (!".".equals(tok.nextToken())) { // NOI18N
187
                    throw new NumberFormatException("Expected dot in code name: " + base); // NOI18N
188
                }
197
                }
189
198
        return null;
190
                expectingPath = true;
191
            }
199
            }
192
        }
193
    }
194
200
195
    /** Parse dependencies from tags.
201
    /** Parse dependencies from tags.
196
    * @param type like Dependency.type
202
    * @param type like Dependency.type
Lines 202-301 Link Here
202
        if (body == null) {
208
        if (body == null) {
203
            return Collections.emptySet();
209
            return Collections.emptySet();
204
        }
210
        }
211
        String[] deps = body.split (",\\s+");
205
212
206
        Set<Dependency> deps = new HashSet<Dependency>(5);
213
        Set <Dependency> result = new HashSet <Dependency> (deps.length);
214
        Map <DependencyKey, Dependency> depsByKey = null;
207
215
208
        // First split on commas.
216
        //Create only if assertions enabled
209
        StringTokenizer tok = new StringTokenizer(body, ","); // NOI18N
217
        assert (depsByKey = new HashMap<DependencyKey, Dependency>()) != null;
210
218
211
        if (!tok.hasMoreTokens()) {
219
        for (String dep : deps) {
212
            throw new IllegalArgumentException("No deps given: \"" + body + "\""); // NOI18N
220
            String[] parts = dep.split ("\\s+"); //NOI18N
221
            if (parts.length == 2 && "".equals(parts[0])) {
222
                parts = new String[] { parts[1] };
213
        }
223
        }
214
215
        Map<DependencyKey, Dependency> depsByKey = new HashMap<DependencyKey, Dependency>(11);
216
217
        while (tok.hasMoreTokens()) {
218
            String onedep = tok.nextToken();
219
            StringTokenizer tok2 = new StringTokenizer(onedep, " \t\n\r"); // NOI18N
220
221
            if (!tok2.hasMoreTokens()) {
222
                throw new IllegalArgumentException("No name in dependency: " + onedep); // NOI18N
223
            }
224
225
            String name = tok2.nextToken();
226
            int comparison;
224
            int comparison;
225
            if (parts.length % 2 == 0 || parts.length > 3) {
226
                throw new IllegalArgumentException ("Bad dependency syntax: " //NOI18N
227
                        + dep + " part count " + parts.length + ": " + 
228
                        Arrays.asList(parts));
229
            }
227
            String version;
230
            String version;
228
231
            if (parts.length == 3) {
229
            if (tok2.hasMoreTokens()) {
232
                if ("=".equals(parts[1])) {
230
                String compthing = tok2.nextToken();
231
232
                if (compthing.equals(">")) { // NOI18N
233
                    comparison = Dependency.COMPARE_SPEC;
234
                } else if (compthing.equals("=")) { // NOI18N
235
                    comparison = Dependency.COMPARE_IMPL;
233
                    comparison = Dependency.COMPARE_IMPL;
234
                } else if (">".equals(parts[1])) {
235
                    comparison = Dependency.COMPARE_SPEC;
236
                } else if ("".equals(parts[1])){
237
                    comparison = Dependency.COMPARE_ANY;
236
                } else {
238
                } else {
237
                    throw new IllegalArgumentException("Strange comparison string: " + compthing); // NOI18N
239
                    throw new IllegalArgumentException ("Unrecognized comparison" + //NOI18N
240
                            " string in " + dep + ":'" + parts[1] + "'"); //NOI18N
238
                }
241
                }
239
242
                version = parts[2];
240
                if (!tok2.hasMoreTokens()) {
241
                    throw new IllegalArgumentException("Comparison string without version: " + onedep); // NOI18N
242
                }
243
244
                version = tok2.nextToken();
245
246
                if (tok2.hasMoreTokens()) {
247
                    throw new IllegalArgumentException("Trailing garbage in dependency: " + onedep); // NOI18N
248
                }
249
250
                if (comparison == Dependency.COMPARE_SPEC) {
251
                    try {
252
                        new SpecificationVersion(version);
253
                    } catch (NumberFormatException nfe) {
254
                        throw new IllegalArgumentException(nfe.toString());
255
                    }
256
                }
257
            } else {
243
            } else {
258
                comparison = Dependency.COMPARE_ANY;
244
                comparison = Dependency.COMPARE_ANY;
259
                version = null;
245
                version = null;
260
            }
246
            }
261
247
            String name = parts[0];
262
            if (type == Dependency.TYPE_MODULE) {
248
            switch (type) {
249
                case Dependency.TYPE_MODULE :
263
                checkCodeName(name, true);
250
                checkCodeName(name, true);
264
251
                    assertRangedComparison (name, comparison, dep);
265
                if ((name.indexOf('-') != -1) && (comparison == Dependency.COMPARE_IMPL)) {
252
                    break;
266
                    throw new IllegalArgumentException(
253
                case Dependency.TYPE_JAVA :
267
                        "Cannot have an implementation dependency on a ranged release version: " + onedep
268
                    ); // NOI18N
269
                }
270
            } else if (type == Dependency.TYPE_PACKAGE) {
271
                int idx = name.indexOf('[');
272
273
                if (idx != -1) {
274
                    if (idx > 0) {
275
                        checkCodeName(name.substring(0, idx), false);
276
                    }
277
278
                    if (name.charAt(name.length() - 1) != ']') {
279
                        throw new IllegalArgumentException("No close bracket on package dep: " + name); // NOI18N
280
                    }
281
282
                    checkCodeName(name.substring(idx + 1, name.length() - 1), false);
283
                } else {
284
                    checkCodeName(name, false);
285
                }
286
287
                if ((idx == 0) && (comparison != Dependency.COMPARE_ANY)) {
288
                    throw new IllegalArgumentException(
289
                        "Cannot use a version comparison on a package dependency when only a sample class is given"
290
                    ); // NOI18N
291
                }
292
293
                if ((idx > 0) && (name.substring(idx + 1, name.length() - 1).indexOf('.') != -1)) {
294
                    throw new IllegalArgumentException(
295
                        "Cannot have a sample class with dots when package is specified"
296
                    ); // NOI18N
297
                }
298
            } else if (type == Dependency.TYPE_JAVA) {
299
                if (!(name.equals(JAVA_NAME) || name.equals(VM_NAME))) { // NOI18N
254
                if (!(name.equals(JAVA_NAME) || name.equals(VM_NAME))) { // NOI18N
300
                    throw new IllegalArgumentException("Java dependency must be on \"Java\" or \"VM\": " + name); // NOI18N
255
                    throw new IllegalArgumentException("Java dependency must be on \"Java\" or \"VM\": " + name); // NOI18N
301
                }
256
                }
Lines 303-321 Link Here
303
                if (comparison == Dependency.COMPARE_ANY) {
258
                if (comparison == Dependency.COMPARE_ANY) {
304
                    throw new IllegalArgumentException("Must give a comparison for a Java dep: " + body); // NOI18N
259
                    throw new IllegalArgumentException("Must give a comparison for a Java dep: " + body); // NOI18N
305
                }
260
                }
306
            } else if (type == Dependency.TYPE_IDE) {
261
                    break;
262
                case Dependency.TYPE_IDE :
307
                if (!(name.equals("IDE"))) { // NOI18N
263
                if (!(name.equals("IDE"))) { // NOI18N
308
309
                    int slash = name.indexOf("/"); // NOI18N
264
                    int slash = name.indexOf("/"); // NOI18N
310
                    boolean ok;
265
                    boolean ok;
311
312
                    if (slash == -1) {
266
                    if (slash == -1) {
313
                        ok = false;
267
                        ok = false;
314
                    } else {
268
                    } else {
315
                        if (!name.substring(0, slash).equals("IDE")) { // NOI18N
269
                        if (!name.substring(0, slash).equals("IDE")) { // NOI18N
316
                            ok = false;
270
                            ok = false;
317
                        }
271
                        }
318
319
                        try {
272
                        try {
320
                            int v = Integer.parseInt(name.substring(slash + 1));
273
                            int v = Integer.parseInt(name.substring(slash + 1));
321
                            ok = (v >= 0);
274
                            ok = (v >= 0);
Lines 323-329 Link Here
323
                            ok = false;
276
                            ok = false;
324
                        }
277
                        }
325
                    }
278
                    }
326
327
                    if (!ok) {
279
                    if (!ok) {
328
                        throw new IllegalArgumentException("Invalid IDE dependency: " + name); // NOI18N
280
                        throw new IllegalArgumentException("Invalid IDE dependency: " + name); // NOI18N
329
                    }
281
                    }
Lines 332-375 Link Here
332
                if (comparison == Dependency.COMPARE_ANY) {
284
                if (comparison == Dependency.COMPARE_ANY) {
333
                    throw new IllegalArgumentException("Must give a comparison for an IDE dep: " + body); // NOI18N
285
                    throw new IllegalArgumentException("Must give a comparison for an IDE dep: " + body); // NOI18N
334
                }
286
                }
335
            } else if (type == Dependency.TYPE_REQUIRES) {
287
                    break;
336
                if (comparison != Dependency.COMPARE_ANY) {
288
                case Dependency.TYPE_PACKAGE :
337
                    throw new IllegalArgumentException("Cannot give a comparison for a token requires dep: " + body); // NOI18N
289
                    int idx = name.indexOf('[');
290
291
                    if (idx != -1) {
292
                        if (idx > 0) {
293
                            checkCodeName(name.substring(0, idx), false);
338
                }
294
                }
339
295
340
                checkCodeName(name, false);
296
                        if (name.charAt(name.length() - 1) != ']') {
341
            } else if (type == Dependency.TYPE_NEEDS) {
297
                            throw new IllegalArgumentException("No close " +
342
                if (comparison != Dependency.COMPARE_ANY) {
298
                                    "bracket on package dep: " + name); // NOI18N
343
                    throw new IllegalArgumentException("Cannot give a comparison for a token needs dep: " + body); // NOI18N
344
                }
299
                }
345
300
301
                        checkCodeName(name.substring(idx + 1, 
302
                                name.length() - 1), false);
303
                    } else {
346
                checkCodeName(name, false);
304
                checkCodeName(name, false);
347
            } else if (type == Dependency.TYPE_RECOMMENDS) {
348
                if (comparison != Dependency.COMPARE_ANY) {
349
                    throw new IllegalArgumentException("Cannot give a comparison for a token needs dep: " + body); // NOI18N
350
                }
305
                }
351
306
352
                checkCodeName(name, false);
307
                    if ((idx == 0) && (comparison != Dependency.COMPARE_ANY)) {
353
            } else {
308
                        throw new IllegalArgumentException(
354
                throw new IllegalArgumentException("unknown type"); // NOI18N
309
                            "Cannot use a version comparison on a package " +
310
                            "dependency when only a sample class is given"
311
                        ); // NOI18N
355
            }
312
            }
356
313
314
                    if ((idx > 0) && (name.substring(idx + 1, name.length() - 1).indexOf('.') != -1)) {
315
                        throw new IllegalArgumentException(
316
                            "Cannot have a sample class with dots when package " +
317
                            "is specified"
318
                        ); // NOI18N
319
                    }
320
                    break;
321
                case Dependency.TYPE_RECOMMENDS :
322
                case Dependency.TYPE_REQUIRES :
323
                case Dependency.TYPE_NEEDS :
324
                    if (comparison != Dependency.COMPARE_ANY) {
325
                        throw new IllegalArgumentException("Cannot " +
326
                                "give a comparison for this type of " +
327
                                "manifest entry: " + body); // NOI18N
328
                    }
329
                    checkCodeName(name, false);
330
                    break;
331
            default :
332
                throw new AssertionError ("" + type);
333
            }
357
            Dependency nue = new Dependency(type, name, comparison, version);
334
            Dependency nue = new Dependency(type, name, comparison, version);
335
            if (depsByKey != null) {
358
            DependencyKey key = new DependencyKey(nue);
336
            DependencyKey key = new DependencyKey(nue);
359
360
            if (depsByKey.containsKey(key)) {
337
            if (depsByKey.containsKey(key)) {
361
                throw new IllegalArgumentException(
338
                throw new IllegalArgumentException(
362
                    "Dependency " + nue + " duplicates the similar dependency " + depsByKey.get(key)
339
                    "Dependency " + nue + " duplicates the similar dependency " + depsByKey.get(key)
363
                ); // NOI18N
340
                ); // NOI18N
364
            } else {
365
                deps.add(nue);
366
                depsByKey.put(key, nue);
367
            }
341
            }
342
                depsByKey.put (key, nue);
368
        }
343
        }
344
            result.add (nue);
345
        }
346
        return result;
347
    }
369
348
370
        return deps;
349
    private static void assertRangedComparison (String name, int comparison, String dep) {
350
        //Don't do this check with assertions off
351
        String err = checkRangedComparison (name, comparison, dep);
352
        try {
353
            assert err == null : err;
354
        } catch (AssertionError e) {
355
            throw new IllegalArgumentException (e.getMessage());
371
    }
356
    }
357
    }
372
358
359
    private static String checkRangedComparison (String name, int comparison, String dep) {
360
        if ((name.indexOf('-') != -1) && (comparison == Dependency.COMPARE_IMPL)) {
361
            return "Cannot have an implementation dependency on a " +
362
                "ranged release version: " + dep; //NOI18N
363
        }          
364
        return null;
365
    }
366
373
    /** Get the type. */
367
    /** Get the type. */
374
    public final int getType() {
368
    public final int getType() {
375
        return type;
369
        return type;
Lines 524-531 Link Here
524
518
525
                break;
519
                break;
526
            }
520
            }
527
528
            //System.err.println("Key for " + d + " is " + this);
529
        }
521
        }
530
522
531
        public int hashCode() {
523
        public int hashCode() {
(-)openide/modules/src/org/openide/modules/SpecificationVersion.java (-1 / +2 lines)
Lines 22-27 Link Here
22
// THIS CLASS OUGHT NOT USE NbBundle NOR org.openide CLASSES
22
// THIS CLASS OUGHT NOT USE NbBundle NOR org.openide CLASSES
23
// OUTSIDE OF openide-util.jar! UI AND FILESYSTEM/DATASYSTEM
23
// OUTSIDE OF openide-util.jar! UI AND FILESYSTEM/DATASYSTEM
24
// INTERACTIONS SHOULD GO ELSEWHERE.
24
// INTERACTIONS SHOULD GO ELSEWHERE.
25
import java.io.Serializable;
25
import java.util.*;
26
import java.util.*;
26
27
27
28
Lines 29-35 Link Here
29
 * @author Jesse Glick
30
 * @author Jesse Glick
30
 * @since 1.24
31
 * @since 1.24
31
 */
32
 */
32
public final class SpecificationVersion implements Comparable {
33
public final class SpecificationVersion implements Comparable, Serializable {
33
    // Might be a bit wasteful of memory, but many SV's are created during
34
    // Might be a bit wasteful of memory, but many SV's are created during
34
    // startup, so best to not have to reparse them each time!
35
    // startup, so best to not have to reparse them each time!
35
    // In fact sharing the int arrays might save a bit of memory overall,
36
    // In fact sharing the int arrays might save a bit of memory overall,

Return to bug 116891