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

(-)a/core.multiview/src/org/netbeans/core/multiview/MultiViewProcessor.java (-12 / +12 lines)
Lines 95-104 Link Here
95
        for (Element e : roundEnv.getElementsAnnotatedWith(MultiViewElement.Registration.class)) {
95
        for (Element e : roundEnv.getElementsAnnotatedWith(MultiViewElement.Registration.class)) {
96
            MultiViewElement.Registration mvr = e.getAnnotation(MultiViewElement.Registration.class);
96
            MultiViewElement.Registration mvr = e.getAnnotation(MultiViewElement.Registration.class);
97
            if (mvr.mimeType().length == 0) {
97
            if (mvr.mimeType().length == 0) {
98
                throw new LayerGenerationException("You must specify mimeType", e);
98
                throw new LayerGenerationException("You must specify mimeType", e, processingEnv, mvr, "mimeType");
99
            }
99
            }
100
            TypeMirror[] exprType = new TypeMirror[1];
100
            TypeMirror[] exprType = new TypeMirror[1];
101
            String[] binAndMethodNames = findDefinition(e, exprType);
101
            String[] binAndMethodNames = findDefinition(e, exprType, mvr);
102
            String fileBaseName = binAndMethodNames[0].replace('.', '-');
102
            String fileBaseName = binAndMethodNames[0].replace('.', '-');
103
            if (binAndMethodNames[1] != null) {
103
            if (binAndMethodNames[1] != null) {
104
                fileBaseName += "-" + binAndMethodNames[1];
104
                fileBaseName += "-" + binAndMethodNames[1];
Lines 108-114 Link Here
108
                f.methodvalue("instanceCreate", MultiViewFactory.class.getName(), "createMultiViewDescription");
108
                f.methodvalue("instanceCreate", MultiViewFactory.class.getName(), "createMultiViewDescription");
109
                f.stringvalue("instanceClass", ContextAwareDescription.class.getName());
109
                f.stringvalue("instanceClass", ContextAwareDescription.class.getName());
110
                f.stringvalue("class", binAndMethodNames[0]);
110
                f.stringvalue("class", binAndMethodNames[0]);
111
                f.bundlevalue("displayName", mvr.displayName());
111
                f.bundlevalue("displayName", mvr.displayName(), mvr, "displayName");
112
                f.stringvalue("iconBase", mvr.iconBase());
112
                f.stringvalue("iconBase", mvr.iconBase());
113
                f.stringvalue("preferredID", mvr.preferredID());
113
                f.stringvalue("preferredID", mvr.preferredID());
114
                f.intvalue("persistenceType", mvr.persistenceType());
114
                f.intvalue("persistenceType", mvr.persistenceType());
Lines 125-137 Link Here
125
        return true;
125
        return true;
126
    }
126
    }
127
127
128
    private String[] findDefinition(Element e, TypeMirror[] type) throws LayerGenerationException {
128
    private String[] findDefinition(Element e, TypeMirror[] type, MultiViewElement.Registration mvr) throws LayerGenerationException {
129
        final TypeMirror lkp = processingEnv.getElementUtils().getTypeElement(Lookup.class.getCanonicalName()).asType();
129
        final TypeMirror lkp = processingEnv.getElementUtils().getTypeElement(Lookup.class.getCanonicalName()).asType();
130
        final TypeMirror mve = processingEnv.getElementUtils().getTypeElement(MultiViewElement.class.getName()).asType();
130
        final TypeMirror mve = processingEnv.getElementUtils().getTypeElement(MultiViewElement.class.getName()).asType();
131
        if (e.getKind() == ElementKind.CLASS) {
131
        if (e.getKind() == ElementKind.CLASS) {
132
            TypeElement clazz = (TypeElement) e;
132
            TypeElement clazz = (TypeElement) e;
133
            if (!processingEnv.getTypeUtils().isAssignable(clazz.asType(), mve)) {
133
            if (!processingEnv.getTypeUtils().isAssignable(clazz.asType(), mve)) {
134
                throw new LayerGenerationException("Not assignable to " + mve, e);
134
                throw new LayerGenerationException("Not assignable to " + mve, e, processingEnv, mvr);
135
            }
135
            }
136
            int constructorCount = 0;
136
            int constructorCount = 0;
137
            CONSTRUCTOR: for (ExecutableElement constructor : ElementFilter.constructorsIn(clazz.getEnclosedElements())) {
137
            CONSTRUCTOR: for (ExecutableElement constructor : ElementFilter.constructorsIn(clazz.getEnclosedElements())) {
Lines 149-180 Link Here
149
                }
149
                }
150
            }
150
            }
151
            if (!clazz.getModifiers().contains(Modifier.PUBLIC)) {
151
            if (!clazz.getModifiers().contains(Modifier.PUBLIC)) {
152
                throw new LayerGenerationException("Class must be public", e);
152
                throw new LayerGenerationException("Class must be public", e, processingEnv, mvr);
153
            }
153
            }
154
            type[0] = e.asType();
154
            type[0] = e.asType();
155
            return new String[] {processingEnv.getElementUtils().getBinaryName(clazz).toString(), null};
155
            return new String[] {processingEnv.getElementUtils().getBinaryName(clazz).toString(), null};
156
        } else {
156
        } else {
157
            ExecutableElement meth = (ExecutableElement) e;
157
            ExecutableElement meth = (ExecutableElement) e;
158
            if (!processingEnv.getTypeUtils().isAssignable(meth.getReturnType(), mve)) {
158
            if (!processingEnv.getTypeUtils().isAssignable(meth.getReturnType(), mve)) {
159
                throw new LayerGenerationException("Not assignable to " + mve, e);
159
                throw new LayerGenerationException("Not assignable to " + mve, e, processingEnv, mvr);
160
            }
160
            }
161
            if (!meth.getModifiers().contains(Modifier.PUBLIC)) {
161
            if (!meth.getModifiers().contains(Modifier.PUBLIC)) {
162
                throw new LayerGenerationException("Method must be public", e);
162
                throw new LayerGenerationException("Method must be public", e, processingEnv, mvr);
163
            }
163
            }
164
            if (!meth.getModifiers().contains(Modifier.STATIC)) {
164
            if (!meth.getModifiers().contains(Modifier.STATIC)) {
165
                throw new LayerGenerationException("Method must be static", e);
165
                throw new LayerGenerationException("Method must be static", e, processingEnv, mvr);
166
            }
166
            }
167
            List<? extends VariableElement> params = meth.getParameters();
167
            List<? extends VariableElement> params = meth.getParameters();
168
            if (params.size() > 1) {
168
            if (params.size() > 1) {
169
                throw new LayerGenerationException("Method must take at most one parameter", e);
169
                throw new LayerGenerationException("Method must take at most one parameter", e, processingEnv, mvr);
170
            }
170
            }
171
            for (VariableElement param : params) {
171
            for (VariableElement param : params) {
172
                if (!param.asType().equals(lkp)) {
172
                if (!param.asType().equals(lkp)) {
173
                    throw new LayerGenerationException("Method parameters may be either Lookup or Project", e);
173
                    throw new LayerGenerationException("Method parameters may be either Lookup or Project", e, processingEnv, mvr);
174
                }
174
                }
175
            }
175
            }
176
            if (!meth.getEnclosingElement().getModifiers().contains(Modifier.PUBLIC)) {
176
            if (!meth.getEnclosingElement().getModifiers().contains(Modifier.PUBLIC)) {
177
                throw new LayerGenerationException("Class must be public", e);
177
                throw new LayerGenerationException("Class must be public", e, processingEnv, mvr);
178
            }
178
            }
179
            type[0] = meth.getReturnType();
179
            type[0] = meth.getReturnType();
180
            return new String[] {
180
            return new String[] {
(-)a/javahelp/nbproject/project.xml (-1 / +1 lines)
Lines 79-85 Link Here
79
                    <build-prerequisite/>
79
                    <build-prerequisite/>
80
                    <compile-dependency/>
80
                    <compile-dependency/>
81
                    <run-dependency>
81
                    <run-dependency>
82
                        <specification-version>7.19</specification-version>
82
                        <specification-version>7.50</specification-version>
83
                    </run-dependency>
83
                    </run-dependency>
84
                </dependency>
84
                </dependency>
85
                <dependency>
85
                <dependency>
(-)a/javahelp/src/org/netbeans/modules/javahelp/HelpSetRegistrationProcessor.java (-2 / +2 lines)
Lines 126-134 Link Here
126
                    }
126
                    }
127
                });
127
                });
128
            } catch (IOException x) {
128
            } catch (IOException x) {
129
                throw new LayerGenerationException("Could not parse " + hs + ": " + x, e);
129
                throw new LayerGenerationException("Could not parse " + hs + ": " + x, e, processingEnv, r, "helpSet");
130
            } catch (SAXException x) {
130
            } catch (SAXException x) {
131
                throw new LayerGenerationException("Could not parse " + hs + ": " + x, e);
131
                throw new LayerGenerationException("Could not parse " + hs + ": " + x, e, processingEnv, r, "helpSet");
132
            }
132
            }
133
            String searchDir = null;
133
            String searchDir = null;
134
            for (Element view : XMLUtil.findSubElements(doc.getDocumentElement())) {
134
            for (Element view : XMLUtil.findSubElements(doc.getDocumentElement())) {
(-)a/openide.awt/nbproject/project.xml (-1 / +1 lines)
Lines 54-60 Link Here
54
                    <build-prerequisite/>
54
                    <build-prerequisite/>
55
                    <compile-dependency/>
55
                    <compile-dependency/>
56
                    <run-dependency>
56
                    <run-dependency>
57
                        <specification-version>7.39</specification-version>
57
                        <specification-version>7.50</specification-version>
58
                    </run-dependency>
58
                    </run-dependency>
59
                </dependency>
59
                </dependency>
60
                <dependency>
60
                <dependency>
(-)a/openide.awt/src/org/netbeans/modules/openide/awt/ActionProcessor.java (-31 / +28 lines)
Lines 41-47 Link Here
41
41
42
import java.awt.event.ActionListener;
42
import java.awt.event.ActionListener;
43
import java.io.IOException;
43
import java.io.IOException;
44
import java.io.InputStream;
45
import java.util.Collections;
44
import java.util.Collections;
46
import java.util.HashSet;
45
import java.util.HashSet;
47
import java.util.Set;
46
import java.util.Set;
Lines 65-71 Link Here
65
import javax.swing.Action;
64
import javax.swing.Action;
66
import javax.swing.JSeparator;
65
import javax.swing.JSeparator;
67
import javax.swing.KeyStroke;
66
import javax.swing.KeyStroke;
68
import javax.tools.FileObject;
69
import javax.tools.StandardLocation;
67
import javax.tools.StandardLocation;
70
import org.openide.awt.ActionID;
68
import org.openide.awt.ActionID;
71
import org.openide.awt.ActionReference;
69
import org.openide.awt.ActionReference;
Lines 179-204 Link Here
179
            ActionRegistration ar = e.getAnnotation(ActionRegistration.class);
177
            ActionRegistration ar = e.getAnnotation(ActionRegistration.class);
180
            ActionID aid = e.getAnnotation(ActionID.class);
178
            ActionID aid = e.getAnnotation(ActionID.class);
181
            if (aid == null) {
179
            if (aid == null) {
182
                throw new LayerGenerationException("@ActionRegistration can only be used together with @ActionID annotation", e);
180
                throw new LayerGenerationException("@ActionRegistration can only be used together with @ActionID annotation", e, processingEnv, ar);
183
            }
181
            }
184
            if (aid.category().startsWith("Actions/")) {
182
            if (aid.category().startsWith("Actions/")) {
185
                throw new LayerGenerationException("@ActionID category() cannot contain /", e);
183
                throw new LayerGenerationException("@ActionID category() cannot contain /", e, processingEnv, aid, "category");
186
            }
184
            }
187
            if (!FQN.matcher(aid.id()).matches()) {
185
            if (!FQN.matcher(aid.id()).matches()) {
188
                throw new LayerGenerationException("@ActionID id() must be valid fully qualified name", e);
186
                throw new LayerGenerationException("@ActionID id() must be valid fully qualified name", e, processingEnv, aid, "id");
189
            }
187
            }
190
            String id = aid.id().replace('.', '-');
188
            String id = aid.id().replace('.', '-');
191
            File f = layer(e).file("Actions/" + aid.category() + "/" + id + ".instance");
189
            File f = layer(e).file("Actions/" + aid.category() + "/" + id + ".instance");
192
            f.bundlevalue("displayName", ar.displayName());
190
            f.bundlevalue("displayName", ar.displayName(), ar, "displayName");
193
            
191
            
194
            String menuText = ar.menuText();
192
            String menuText = ar.menuText();
195
            if(!menuText.isEmpty()) {
193
            if(!menuText.isEmpty()) {
196
                f.bundlevalue("menuText", menuText);
194
                f.bundlevalue("menuText", menuText, ar, "menuText");
197
            }
195
            }
198
196
199
            String popupText = ar.popupText();
197
            String popupText = ar.popupText();
200
            if (!popupText.isEmpty()) {
198
            if (!popupText.isEmpty()) {
201
                f.bundlevalue("popupText", popupText);
199
                f.bundlevalue("popupText", popupText, ar, "popupText");
202
            }
200
            }
203
            
201
            
204
            String key;
202
            String key;
Lines 212-236 Link Here
212
                    !e.getModifiers().contains(Modifier.STATIC) ||
210
                    !e.getModifiers().contains(Modifier.STATIC) ||
213
                    !e.getModifiers().contains(Modifier.FINAL)
211
                    !e.getModifiers().contains(Modifier.FINAL)
214
                ) {
212
                ) {
215
                    throw new LayerGenerationException("Only static string constant fields can be annotated", e);
213
                    throw new LayerGenerationException("Only static string constant fields can be annotated", e, processingEnv, ar);
216
                }
214
                }
217
                if (ar.key().length() != 0) {
215
                if (ar.key().length() != 0) {
218
                    throw new LayerGenerationException("When annotating field, one cannot define key()", e);
216
                    throw new LayerGenerationException("When annotating field, one cannot define key()", e, processingEnv, ar, "key");
219
                }
217
                }
220
                
218
                
221
                createDelegate = false;
219
                createDelegate = false;
222
                key = var.getConstantValue().toString();
220
                key = var.getConstantValue().toString();
223
            } else if (e.getKind() == ElementKind.CLASS) {
221
            } else if (e.getKind() == ElementKind.CLASS) {
224
                if (!isAssignable(e.asType(), actionListener)) {
222
                if (!isAssignable(e.asType(), actionListener)) {
225
                    throw new LayerGenerationException("Class annotated with @ActionRegistration must implement java.awt.event.ActionListener!", e);
223
                    throw new LayerGenerationException("Class annotated with @ActionRegistration must implement java.awt.event.ActionListener!", e, processingEnv, ar);
226
                }
224
                }
227
                if (!e.getModifiers().contains(Modifier.PUBLIC)) {
225
                if (!e.getModifiers().contains(Modifier.PUBLIC)) {
228
                    throw new LayerGenerationException("Class has to be public", e);
226
                    throw new LayerGenerationException("Class has to be public", e, processingEnv, ar);
229
                }
227
                }
230
                key = ar.key();
228
                key = ar.key();
231
            } else {
229
            } else {
232
                assert e.getKind() == ElementKind.METHOD : e;
230
                assert e.getKind() == ElementKind.METHOD : e;
233
                layer(e).instanceFile("dummy", null, ActionListener.class);
231
                layer(e).instanceFile("dummy", null, ActionListener.class, ar, null);
234
                key = ar.key();
232
                key = ar.key();
235
            }
233
            }
236
234
Lines 244-250 Link Here
244
            
242
            
245
            if (direct) {
243
            if (direct) {
246
                if (key.length() != 0) {
244
                if (key.length() != 0) {
247
                    throw new LayerGenerationException("Cannot specify key and implement Presenter interface", e);
245
                    throw new LayerGenerationException("Cannot specify key and implement Presenter interface", e, processingEnv, ar, "key");
248
                }
246
                }
249
                f.instanceAttribute("instanceCreate", Action.class);
247
                f.instanceAttribute("instanceCreate", Action.class);
250
            } else {
248
            } else {
Lines 259-267 Link Here
259
                }
257
                }
260
                if (createDelegate) {
258
                if (createDelegate) {
261
                    try {
259
                    try {
262
                        f.instanceAttribute("delegate", ActionListener.class);
260
                        f.instanceAttribute("delegate", ActionListener.class, ar, null);
263
                    } catch (LayerGenerationException ex) {
261
                    } catch (LayerGenerationException ex) {
264
                        generateContext(e, f);
262
                        generateContext(e, f, ar);
265
                    }
263
                    }
266
                }
264
                }
267
                if (ar.iconBase().length() > 0) {
265
                if (ar.iconBase().length() > 0) {
Lines 274-285 Link Here
274
                        } catch (IOException ex) {
272
                        } catch (IOException ex) {
275
                            continue;
273
                            continue;
276
                        } catch (IllegalArgumentException x) {
274
                        } catch (IllegalArgumentException x) {
277
                            throw new LayerGenerationException("Problem with " + ar.iconBase() + " (should be resource path with no leading slash)", e);
275
                            throw new LayerGenerationException("Problem with " + ar.iconBase() + " (should be resource path with no leading slash)", e, processingEnv, ar, "iconBase");
278
                        }
276
                        }
279
                    }
277
                    }
280
                    if (!found) {
278
                    if (!found) {
281
                        throw new LayerGenerationException(
279
                        throw new LayerGenerationException(
282
                            "Cannot find iconBase file at " + ar.iconBase(), e
280
                            "Cannot find iconBase file at " + ar.iconBase(), e, processingEnv, ar, "iconBase"
283
                        );
281
                        );
284
                    }
282
                    }
285
                    f.stringvalue("iconBase", ar.iconBase());
283
                    f.stringvalue("iconBase", ar.iconBase());
Lines 310-344 Link Here
310
            if (e.getAnnotation(ActionRegistration.class) != null) {
308
            if (e.getAnnotation(ActionRegistration.class) != null) {
311
                continue;
309
                continue;
312
            }
310
            }
311
            ActionReference ref = e.getAnnotation(ActionReference.class);
313
            ActionID id = e.getAnnotation(ActionID.class);
312
            ActionID id = e.getAnnotation(ActionID.class);
314
            if (id != null) {
313
            if (id != null) {
315
                ActionReference ref = e.getAnnotation(ActionReference.class);
316
                processReferences(e, ref, id);
314
                processReferences(e, ref, id);
317
                continue;
315
                continue;
318
            }
316
            }
319
            throw new LayerGenerationException("Don't use @ActionReference without @ActionID", e);
317
            throw new LayerGenerationException("Don't use @ActionReference without @ActionID", e, processingEnv, ref);
320
        }
318
        }
321
        for (Element e : roundEnv.getElementsAnnotatedWith(ActionReferences.class)) {
319
        for (Element e : roundEnv.getElementsAnnotatedWith(ActionReferences.class)) {
322
            if (e.getAnnotation(ActionRegistration.class) != null) {
320
            if (e.getAnnotation(ActionRegistration.class) != null) {
323
                continue;
321
                continue;
324
            }
322
            }
323
            ActionReferences refs = e.getAnnotation(ActionReferences.class);
325
            if (e.getKind() != ElementKind.PACKAGE) {
324
            if (e.getKind() != ElementKind.PACKAGE) {
326
                ActionID id = e.getAnnotation(ActionID.class);
325
                ActionID id = e.getAnnotation(ActionID.class);
327
                if (id == null) {
326
                if (id == null) {
328
                    throw new LayerGenerationException("Don't use @ActionReferences without @ActionRegistration", e);
327
                    throw new LayerGenerationException("Don't use @ActionReferences without @ActionRegistration", e, processingEnv, refs);
329
                }
328
                }
330
                ActionReferences refs = e.getAnnotation(ActionReferences.class);
331
                for (ActionReference actionReference : refs.value()) {
329
                for (ActionReference actionReference : refs.value()) {
332
                    if (!actionReference.id().id().isEmpty() || !actionReference.id().category().isEmpty()) {
330
                    if (!actionReference.id().id().isEmpty() || !actionReference.id().category().isEmpty()) {
333
                        throw new LayerGenerationException("Don't specify additional id=@ActionID(...) when using @ActionID on the element", e);
331
                        throw new LayerGenerationException("Don't specify additional id=@ActionID(...) when using @ActionID on the element", e, processingEnv, actionReference.id());
334
                    }
332
                    }
335
                    processReferences(e, actionReference, id);
333
                    processReferences(e, actionReference, id);
336
                }
334
                }
337
            } else {
335
            } else {
338
                ActionReferences refs = e.getAnnotation(ActionReferences.class);
339
                for (ActionReference actionReference : refs.value()) {
336
                for (ActionReference actionReference : refs.value()) {
340
                    if (actionReference.id().id().isEmpty() || actionReference.id().category().isEmpty()) {
337
                    if (actionReference.id().id().isEmpty() || actionReference.id().category().isEmpty()) {
341
                        throw new LayerGenerationException("Specify real id=@ActionID(...)", e);
338
                        throw new LayerGenerationException("Specify real id=@ActionID(...)", e, processingEnv, actionReference.id());
342
                    }
339
                    }
343
                    processReferences(e, actionReference, actionReference.id());
340
                    processReferences(e, actionReference, actionReference.id());
344
                }
341
                }
Lines 352-358 Link Here
352
        return e == null ? null : e.asType();
349
        return e == null ? null : e.asType();
353
    }
350
    }
354
351
355
    private void generateContext(Element e, File f) throws LayerGenerationException {
352
    private void generateContext(Element e, File f, ActionRegistration ar) throws LayerGenerationException {
356
        ExecutableElement ee = null;
353
        ExecutableElement ee = null;
357
        ExecutableElement candidate = null;
354
        ExecutableElement candidate = null;
358
        for (ExecutableElement element : ElementFilter.constructorsIn(e.getEnclosedElements())) {
355
        for (ExecutableElement element : ElementFilter.constructorsIn(e.getEnclosedElements())) {
Lines 362-368 Link Here
362
                    continue;
359
                    continue;
363
                }
360
                }
364
                if (ee != null) {
361
                if (ee != null) {
365
                    throw new LayerGenerationException("Only one public constructor allowed", e); // NOI18N
362
                    throw new LayerGenerationException("Only one public constructor allowed", e, processingEnv, ar); // NOI18N
366
                }
363
                }
367
                ee = element;
364
                ee = element;
368
            }
365
            }
Lines 412-418 Link Here
412
    private void processReferences(Element e, ActionReference ref, ActionID aid) throws LayerGenerationException {
409
    private void processReferences(Element e, ActionReference ref, ActionID aid) throws LayerGenerationException {
413
        if (!ref.id().category().isEmpty() && !ref.id().id().isEmpty()) {
410
        if (!ref.id().category().isEmpty() && !ref.id().id().isEmpty()) {
414
            if (!aid.id().equals(ref.id().id()) || !aid.category().equals(ref.id().category())) {
411
            if (!aid.id().equals(ref.id().id()) || !aid.category().equals(ref.id().category())) {
415
                throw new LayerGenerationException("Can't specify id() attribute when @ActionID provided on the element", e);
412
                throw new LayerGenerationException("Can't specify id() attribute when @ActionID provided on the element", e, processingEnv, aid);
416
            }
413
            }
417
        }
414
        }
418
        String name = ref.name();
415
        String name = ref.name();
Lines 427-433 Link Here
427
                    "Registrations in Shortcuts folder need to represent a key. "
424
                    "Registrations in Shortcuts folder need to represent a key. "
428
                    + "Specify value for 'name' attribute.\n"
425
                    + "Specify value for 'name' attribute.\n"
429
                    + "See org.openide.util.Utilities.stringToKeys for possible values. Current "
426
                    + "See org.openide.util.Utilities.stringToKeys for possible values. Current "
430
                    + "name=\"" + name + "\" is not valid.\n"
427
                    + "name=\"" + name + "\" is not valid.\n", e, processingEnv, ref, "path"
431
                );
428
                );
432
            }
429
            }
433
        }
430
        }
Lines 439-445 Link Here
439
        
436
        
440
        if (ref.separatorAfter() != Integer.MAX_VALUE) {
437
        if (ref.separatorAfter() != Integer.MAX_VALUE) {
441
            if (ref.position() == Integer.MAX_VALUE || ref.position() >= ref.separatorAfter()) {
438
            if (ref.position() == Integer.MAX_VALUE || ref.position() >= ref.separatorAfter()) {
442
                throw new LayerGenerationException("separatorAfter() must be greater than position()", e);
439
                throw new LayerGenerationException("separatorAfter() must be greater than position()", e, processingEnv, ref);
443
            }
440
            }
444
            File after = layer(e).file(ref.path() + "/" + name + "-separatorAfter.instance");
441
            File after = layer(e).file(ref.path() + "/" + name + "-separatorAfter.instance");
445
            after.newvalue("instanceCreate", JSeparator.class.getName());
442
            after.newvalue("instanceCreate", JSeparator.class.getName());
Lines 448-454 Link Here
448
        }
445
        }
449
        if (ref.separatorBefore() != Integer.MAX_VALUE) {
446
        if (ref.separatorBefore() != Integer.MAX_VALUE) {
450
            if (ref.position() == Integer.MAX_VALUE || ref.position() <= ref.separatorBefore()) {
447
            if (ref.position() == Integer.MAX_VALUE || ref.position() <= ref.separatorBefore()) {
451
                throw new LayerGenerationException("separatorBefore() must be lower than position()", e);
448
                throw new LayerGenerationException("separatorBefore() must be lower than position()", e, processingEnv, ref);
452
            }
449
            }
453
            File before = layer(e).file(ref.path() + "/" + name + "-separatorBefore.instance");
450
            File before = layer(e).file(ref.path() + "/" + name + "-separatorBefore.instance");
454
            before.newvalue("instanceCreate", JSeparator.class.getName());
451
            before.newvalue("instanceCreate", JSeparator.class.getName());
(-)a/openide.filesystems/apichanges.xml (-1 / +23 lines)
Lines 49-54 Link Here
49
        <apidef name="filesystems">Filesystems API</apidef>
49
        <apidef name="filesystems">Filesystems API</apidef>
50
    </apidefs>
50
    </apidefs>
51
    <changes>
51
    <changes>
52
        <change id="LayerGenerationException_194545">
53
            <api name="filesystems"/>
54
            <summary><code>LayerGenerationException</code> has new constructors</summary>
55
            <version major="7" minor="50"/>
56
            <date day="25" month="7" year="2011"/>
57
            <author login="jglick"/>
58
            <compatibility addition="yes">
59
                <p>
60
                    Code using the constructors not specifying an annotation should now do so.
61
                </p>
62
            </compatibility>
63
            <description>
64
                <p>
65
                    <code>LayerGenerationException</code> has new constructors making it easier to specify
66
                    the particular annotation responsible for a problem.
67
                    Some methods in <code>LayerBuilder</code> have new overloads to take advantage of it.
68
                </p>
69
            </description>
70
            <class package="org.openide.filesystems.annotations" name="LayerGenerationException"/>
71
            <class package="org.openide.filesystems.annotations" name="LayerBuilder"/>
72
            <issue number="194545"/>
73
        </change>
52
        <change id="getConfigObject">
74
        <change id="getConfigObject">
53
            <api name="filesystems"/>
75
            <api name="filesystems"/>
54
            <summary>FileUtil.getConfigObject</summary>
76
            <summary>FileUtil.getConfigObject</summary>
Lines 59-65 Link Here
59
            <description>
81
            <description>
60
                <p>
82
                <p>
61
                    One can convert files in SystemFileSystem to Object with
83
                    One can convert files in SystemFileSystem to Object with
62
                    a 
84
                    a
63
                    <a href="@TOP@org/openide/filesystems/FileUtil.html#getConfigObject(java.lang.String,%20java.lang.Class)">
85
                    <a href="@TOP@org/openide/filesystems/FileUtil.html#getConfigObject(java.lang.String,%20java.lang.Class)">
64
                    single utility method</a>.
86
                    single utility method</a>.
65
                </p>
87
                </p>
(-)a/openide.filesystems/manifest.mf (-1 / +1 lines)
Lines 2-6 Link Here
2
OpenIDE-Module: org.openide.filesystems
2
OpenIDE-Module: org.openide.filesystems
3
OpenIDE-Module-Localizing-Bundle: org/openide/filesystems/Bundle.properties
3
OpenIDE-Module-Localizing-Bundle: org/openide/filesystems/Bundle.properties
4
OpenIDE-Module-Layer: org/openide/filesystems/resources/layer.xml
4
OpenIDE-Module-Layer: org/openide/filesystems/resources/layer.xml
5
OpenIDE-Module-Specification-Version: 7.49
5
OpenIDE-Module-Specification-Version: 7.50
6
6
(-)a/openide.filesystems/src/org/openide/filesystems/annotations/LayerBuilder.java (-18 / +89 lines)
Lines 45-51 Link Here
45
import java.io.FileNotFoundException;
45
import java.io.FileNotFoundException;
46
import java.io.IOException;
46
import java.io.IOException;
47
import java.io.InputStream;
47
import java.io.InputStream;
48
import java.io.ObjectOutputStream;
48
import java.lang.annotation.Annotation;
49
import java.net.URI;
49
import java.net.URI;
50
import java.util.Arrays;
50
import java.util.Arrays;
51
import java.util.LinkedHashMap;
51
import java.util.LinkedHashMap;
Lines 146-153 Link Here
146
     *                                  {@linkplain TypeElement class} or {@linkplain ExecutableElement method}
146
     *                                  {@linkplain TypeElement class} or {@linkplain ExecutableElement method}
147
     * @throws LayerGenerationException if the associated element would not be loadable as an instance of the specified type
147
     * @throws LayerGenerationException if the associated element would not be loadable as an instance of the specified type
148
     */
148
     */
149
    public File instanceFile(String path, String name, Class type) throws IllegalArgumentException, LayerGenerationException {
149
    public File instanceFile(String path, String name, Class<?> type) throws IllegalArgumentException, LayerGenerationException {
150
        String[] clazzOrMethod = instantiableClassOrMethod(type);
150
        return instanceFile(path, name, type, null, null);
151
    }
152
    /**
153
     * Generates an instance file whose {@code InstanceCookie} would load the associated class or method.
154
     * Useful for {@link LayerGeneratingProcessor}s which define layer fragments which instantiate Java objects from the annotated code.
155
     * <p>While you can pick a specific instance file name, if possible you should pass null for {@code name}
156
     * as using the generated name will help avoid accidental name collisions between annotations.
157
     * @param path path to folder of instance file, e.g. {@code "Menu/File"}
158
     * @param name instance file basename, e.g. {@code "my-menu-Item"}, or null to pick a name according to the element
159
     * @param type a type to which the instance ought to be assignable, or null to skip this check
160
     * @param annotation as in {@link LayerGenerationException#LayerGenerationException(String,Element,ProcessingEnvironment,Annotation,String)}
161
     * @param annotationMethod as in {@link LayerGenerationException#LayerGenerationException(String,Element,ProcessingEnvironment,Annotation,String)}
162
     * @return an instance file (call {@link File#write} to finalize)
163
     * @throws IllegalArgumentException if the builder is not associated with exactly one
164
     *                                  {@linkplain TypeElement class} or {@linkplain ExecutableElement method}
165
     * @throws LayerGenerationException if the associated element would not be loadable as an instance of the specified type
166
     * @since 7.50
167
     */
168
    public File instanceFile(String path, String name, Class<?> type, Annotation annotation, String annotationMethod) throws IllegalArgumentException, LayerGenerationException {
169
        String[] clazzOrMethod = instantiableClassOrMethod(type, annotation, annotationMethod);
151
        String clazz = clazzOrMethod[0];
170
        String clazz = clazzOrMethod[0];
152
        String method = clazzOrMethod[1];
171
        String method = clazzOrMethod[1];
153
        String basename;
172
        String basename;
Lines 185-191 Link Here
185
     * @since org.openide.filesystems 7.27
204
     * @since org.openide.filesystems 7.27
186
     */
205
     */
187
    public File instanceFile(String path, String name) throws IllegalArgumentException, LayerGenerationException {
206
    public File instanceFile(String path, String name) throws IllegalArgumentException, LayerGenerationException {
188
        String[] clazzOrMethod = instantiableClassOrMethod(null);
207
        return instanceFile(path, name, null, null);
208
    }
209
    /**
210
     * Generates an instance file that is <em>not initialized</em> with an instance.
211
     * Useful for {@link LayerGeneratingProcessor}s which define layer fragments
212
     * which indirectly instantiate Java objects from the annotated code via a generic factory method.
213
     * Invoke the factory using {@link File#methodvalue} on {@code instanceCreate}
214
     * and configure it with a {@link File#instanceAttribute} appropriate to the factory.
215
     * <p>While you can pick a specific instance file name, if possible you should pass null for {@code name}
216
     * as using the generated name will help avoid accidental name collisions between annotations.
217
     * @param path path to folder of instance file, e.g. {@code "Menu/File"}
218
     * @param name instance file basename, e.g. {@code "my-menu-Item"}, or null to pick a name according to the element
219
     * @param annotation as in {@link LayerGenerationException#LayerGenerationException(String,Element,ProcessingEnvironment,Annotation,String)}
220
     * @param annotationMethod as in {@link LayerGenerationException#LayerGenerationException(String,Element,ProcessingEnvironment,Annotation,String)}
221
     * @return an instance file (call {@link File#write} to finalize)
222
     * @throws IllegalArgumentException if the builder is not associated with exactly one
223
     *                                  {@linkplain TypeElement class} or {@linkplain ExecutableElement method}
224
     * @throws LayerGenerationException if the associated element would not be loadable as an instance
225
     * @since org.openide.filesystems 7.50
226
     */
227
    public File instanceFile(String path, String name, Annotation annotation, String annotationMethod) throws IllegalArgumentException, LayerGenerationException {
228
        String[] clazzOrMethod = instantiableClassOrMethod(null, annotation, annotationMethod);
189
        String clazz = clazzOrMethod[0];
229
        String clazz = clazzOrMethod[0];
190
        String method = clazzOrMethod[1];
230
        String method = clazzOrMethod[1];
191
        String basename;
231
        String basename;
Lines 200-206 Link Here
200
        return file(path + "/" + basename + ".instance");
240
        return file(path + "/" + basename + ".instance");
201
    }
241
    }
202
242
203
    private String[] instantiableClassOrMethod(Class type) throws IllegalArgumentException, LayerGenerationException {
243
    private String[] instantiableClassOrMethod(Class<?> type, Annotation annotation, String annotationMethod) throws IllegalArgumentException, LayerGenerationException {
204
        if (originatingElement == null) {
244
        if (originatingElement == null) {
205
            throw new IllegalArgumentException("Only applicable to builders with exactly one associated element");
245
            throw new IllegalArgumentException("Only applicable to builders with exactly one associated element");
206
        }
246
        }
Lines 212-218 Link Here
212
            case CLASS: {
252
            case CLASS: {
213
                String clazz = processingEnv.getElementUtils().getBinaryName((TypeElement) originatingElement).toString();
253
                String clazz = processingEnv.getElementUtils().getBinaryName((TypeElement) originatingElement).toString();
214
                if (originatingElement.getModifiers().contains(Modifier.ABSTRACT)) {
254
                if (originatingElement.getModifiers().contains(Modifier.ABSTRACT)) {
215
                    throw new LayerGenerationException(clazz + " must not be abstract", originatingElement);
255
                    throw new LayerGenerationException(clazz + " must not be abstract", originatingElement, processingEnv, annotation, annotationMethod);
216
                }
256
                }
217
                {
257
                {
218
                    boolean hasDefaultCtor = false;
258
                    boolean hasDefaultCtor = false;
Lines 223-236 Link Here
223
                        }
263
                        }
224
                    }
264
                    }
225
                    if (!hasDefaultCtor) {
265
                    if (!hasDefaultCtor) {
226
                        throw new LayerGenerationException(clazz + " must have a no-argument constructor", originatingElement);
266
                        throw new LayerGenerationException(clazz + " must have a no-argument constructor", originatingElement, processingEnv, annotation, annotationMethod);
227
                    }
267
                    }
228
                }
268
                }
229
                if (typeMirror != null && !processingEnv.getTypeUtils().isAssignable(originatingElement.asType(), typeMirror)) {
269
                if (typeMirror != null && !processingEnv.getTypeUtils().isAssignable(originatingElement.asType(), typeMirror)) {
230
                    throw new LayerGenerationException(clazz + " is not assignable to " + typeMirror, originatingElement);
270
                    throw new LayerGenerationException(clazz + " is not assignable to " + typeMirror, originatingElement, processingEnv, annotation, annotationMethod);
231
                }
271
                }
232
                if (!originatingElement.getModifiers().contains(Modifier.PUBLIC)) {
272
                if (!originatingElement.getModifiers().contains(Modifier.PUBLIC)) {
233
                    throw new LayerGenerationException(clazz + " is not public", originatingElement);
273
                    throw new LayerGenerationException(clazz + " is not public", originatingElement, processingEnv, annotation, annotationMethod);
234
                }
274
                }
235
                return new String[] {clazz, null};
275
                return new String[] {clazz, null};
236
            }
276
            }
Lines 238-250 Link Here
238
                String clazz = processingEnv.getElementUtils().getBinaryName((TypeElement) originatingElement.getEnclosingElement()).toString();
278
                String clazz = processingEnv.getElementUtils().getBinaryName((TypeElement) originatingElement.getEnclosingElement()).toString();
239
                String method = originatingElement.getSimpleName().toString();
279
                String method = originatingElement.getSimpleName().toString();
240
                if (!originatingElement.getModifiers().contains(Modifier.STATIC)) {
280
                if (!originatingElement.getModifiers().contains(Modifier.STATIC)) {
241
                    throw new LayerGenerationException(clazz + "." + method + " must be static", originatingElement);
281
                    throw new LayerGenerationException(clazz + "." + method + " must be static", originatingElement, processingEnv, annotation, annotationMethod);
242
                }
282
                }
243
                if (!((ExecutableElement) originatingElement).getParameters().isEmpty()) {
283
                if (!((ExecutableElement) originatingElement).getParameters().isEmpty()) {
244
                    throw new LayerGenerationException(clazz + "." + method + " must not take arguments", originatingElement);
284
                    throw new LayerGenerationException(clazz + "." + method + " must not take arguments", originatingElement, processingEnv, annotation, annotationMethod);
245
                }
285
                }
246
                if (typeMirror != null && !processingEnv.getTypeUtils().isAssignable(((ExecutableElement) originatingElement).getReturnType(), typeMirror)) {
286
                if (typeMirror != null && !processingEnv.getTypeUtils().isAssignable(((ExecutableElement) originatingElement).getReturnType(), typeMirror)) {
247
                    throw new LayerGenerationException(clazz + "." + method + " is not assignable to " + typeMirror, originatingElement);
287
                    throw new LayerGenerationException(clazz + "." + method + " is not assignable to " + typeMirror, originatingElement, processingEnv, annotation, annotationMethod);
248
                }
288
                }
249
                return new String[] {clazz, method};
289
                return new String[] {clazz, method};
250
            }
290
            }
Lines 485-492 Link Here
485
         * @throws IllegalArgumentException if the associated element is not a {@linkplain TypeElement class} or {@linkplain ExecutableElement method}
525
         * @throws IllegalArgumentException if the associated element is not a {@linkplain TypeElement class} or {@linkplain ExecutableElement method}
486
         * @throws LayerGenerationException if the associated element would not be loadable as an instance of the specified type
526
         * @throws LayerGenerationException if the associated element would not be loadable as an instance of the specified type
487
         */
527
         */
488
        public File instanceAttribute(String attr, Class type) throws IllegalArgumentException, LayerGenerationException {
528
        public File instanceAttribute(String attr, Class<?> type) throws IllegalArgumentException, LayerGenerationException {
489
            String[] clazzOrMethod = instantiableClassOrMethod(type);
529
            return instanceAttribute(attr, type, null, null);
530
        }
531
        /**
532
         * Adds an attribute to load the associated class or method.
533
         * Useful for {@link LayerGeneratingProcessor}s which define layer fragments which instantiate Java objects from the annotated code.
534
         * @param attr the attribute name
535
         * @param type a type to which the instance ought to be assignable, or null to skip this check
536
         * @param annotation as in {@link LayerGenerationException#LayerGenerationException(String,Element,ProcessingEnvironment,Annotation,String)}
537
         * @param annotationMethod as in {@link LayerGenerationException#LayerGenerationException(String,Element,ProcessingEnvironment,Annotation,String)}
538
         * @return this builder
539
         * @throws IllegalArgumentException if the associated element is not a {@linkplain TypeElement class} or {@linkplain ExecutableElement method}
540
         * @throws LayerGenerationException if the associated element would not be loadable as an instance of the specified type
541
         * @since 7.50
542
         */
543
        public File instanceAttribute(String attr, Class<?> type, Annotation annotation, String annotationMethod) throws IllegalArgumentException, LayerGenerationException {
544
            String[] clazzOrMethod = instantiableClassOrMethod(type, annotation, annotationMethod);
490
            if (clazzOrMethod[1] == null) {
545
            if (clazzOrMethod[1] == null) {
491
                newvalue(attr, clazzOrMethod[0]);
546
                newvalue(attr, clazzOrMethod[0]);
492
            } else {
547
            } else {
Lines 518-523 Link Here
518
         * @throws LayerGenerationException if a bundle key is requested but it cannot be found in sources
573
         * @throws LayerGenerationException if a bundle key is requested but it cannot be found in sources
519
         */
574
         */
520
        public File bundlevalue(String attr, String label) throws LayerGenerationException {
575
        public File bundlevalue(String attr, String label) throws LayerGenerationException {
576
            return bundlevalue(attr, label, null, null);
577
        }
578
        /**
579
         * Adds an attribute for a possibly localized string.
580
         * @param attr the attribute name
581
         * @param label either a general string to store as is, or a resource bundle reference
582
         *              such as {@code "my.module.Bundle#some_key"},
583
         *              or just {@code "#some_key"} to load from a {@code "Bundle"}
584
         *              in the same package as the element associated with this builder (if exactly one)
585
         * @param annotation as in {@link LayerGenerationException#LayerGenerationException(String,Element,ProcessingEnvironment,Annotation,String)}
586
         * @param annotationMethod as in {@link LayerGenerationException#LayerGenerationException(String,Element,ProcessingEnvironment,Annotation,String)}
587
         * @return this builder
588
         * @throws LayerGenerationException if a bundle key is requested but it cannot be found in sources
589
         * @since 7.50
590
         */
591
        public File bundlevalue(String attr, String label, Annotation annotation, String annotationMethod) throws LayerGenerationException {
521
            String javaIdentifier = "(?:\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*)";
592
            String javaIdentifier = "(?:\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*)";
522
            Matcher m = Pattern.compile("((?:" + javaIdentifier + "\\.)+[^\\s.#]+)?#(\\S*)").matcher(label);
593
            Matcher m = Pattern.compile("((?:" + javaIdentifier + "\\.)+[^\\s.#]+)?#(\\S*)").matcher(label);
523
            if (m.matches()) {
594
            if (m.matches()) {
Lines 533-546 Link Here
533
                    }
604
                    }
534
                    bundle = ((PackageElement) referenceElement).getQualifiedName() + ".Bundle";
605
                    bundle = ((PackageElement) referenceElement).getQualifiedName() + ".Bundle";
535
                }
606
                }
536
                verifyBundleKey(bundle, key, m.group(1) == null);
607
                verifyBundleKey(bundle, key, m.group(1) == null, annotation, annotationMethod);
537
                bundlevalue(attr, bundle, key);
608
                bundlevalue(attr, bundle, key);
538
            } else {
609
            } else {
539
                stringvalue(attr, label);
610
                stringvalue(attr, label);
540
            }
611
            }
541
            return this;
612
            return this;
542
        }
613
        }
543
        private void verifyBundleKey(String bundle, String key, boolean samePackage) throws LayerGenerationException {
614
        private void verifyBundleKey(String bundle, String key, boolean samePackage, Annotation annotation, String annotationMethod) throws LayerGenerationException {
544
            if (processingEnv == null) {
615
            if (processingEnv == null) {
545
                return;
616
                return;
546
            }
617
            }
Lines 572-584 Link Here
572
                    Properties p = new Properties();
643
                    Properties p = new Properties();
573
                    p.load(is);
644
                    p.load(is);
574
                    if (p.getProperty(key) == null) {
645
                    if (p.getProperty(key) == null) {
575
                        throw new LayerGenerationException("No key '" + key + "' found in " + resource, originatingElement);
646
                        throw new LayerGenerationException("No key '" + key + "' found in " + resource, originatingElement, processingEnv, annotation, annotationMethod);
576
                    }
647
                    }
577
                } finally {
648
                } finally {
578
                    is.close();
649
                    is.close();
579
                }
650
                }
580
            } catch (IOException x) {
651
            } catch (IOException x) {
581
                throw new LayerGenerationException("Could not open " + resource + ": " + x, originatingElement);
652
                throw new LayerGenerationException("Could not open " + resource + ": " + x, originatingElement, processingEnv, annotation, annotationMethod);
582
            }
653
            }
583
        }
654
        }
584
655
(-)a/openide.filesystems/src/org/openide/filesystems/annotations/LayerGenerationException.java (-3 / +89 lines)
Lines 42-54 Link Here
42
42
43
package org.openide.filesystems.annotations;
43
package org.openide.filesystems.annotations;
44
44
45
import java.lang.annotation.Annotation;
46
import java.util.Map;
45
import javax.annotation.processing.Messager;
47
import javax.annotation.processing.Messager;
48
import javax.annotation.processing.ProcessingEnvironment;
46
import javax.lang.model.element.AnnotationMirror;
49
import javax.lang.model.element.AnnotationMirror;
47
import javax.lang.model.element.AnnotationValue;
50
import javax.lang.model.element.AnnotationValue;
48
import javax.lang.model.element.Element;
51
import javax.lang.model.element.Element;
52
import javax.lang.model.element.ExecutableElement;
53
import javax.lang.model.element.TypeElement;
49
54
50
/**
55
/**
51
 * Exception thrown when a layer entry cannot be generated due to erroneous sources.
56
 * Exception thrown when a layer entry cannot be generated due to erroneous sources.
57
 * @see LayerGeneratingProcessor
52
 * @since org.openide.filesystems 7.15
58
 * @since org.openide.filesystems 7.15
53
 */
59
 */
54
public class LayerGenerationException extends Exception {
60
public class LayerGenerationException extends Exception {
Lines 63-69 Link Here
63
     * @see Messager#printMessage(javax.tools.Diagnostic.Kind, CharSequence)
69
     * @see Messager#printMessage(javax.tools.Diagnostic.Kind, CharSequence)
64
     */
70
     */
65
    public LayerGenerationException(String message) {
71
    public LayerGenerationException(String message) {
66
        this(message, null, null, null);
72
        this(message, (Element) null, (AnnotationMirror) null, (AnnotationValue) null);
67
    }
73
    }
68
74
69
    /**
75
    /**
Lines 73-79 Link Here
73
     * @see Messager#printMessage(javax.tools.Diagnostic.Kind, CharSequence, Element)
79
     * @see Messager#printMessage(javax.tools.Diagnostic.Kind, CharSequence, Element)
74
     */
80
     */
75
    public LayerGenerationException(String message, Element erroneousElement) {
81
    public LayerGenerationException(String message, Element erroneousElement) {
76
        this(message, erroneousElement, null, null);
82
        this(message, erroneousElement, (AnnotationMirror) null, (AnnotationValue) null);
77
    }
83
    }
78
84
79
    /**
85
    /**
Lines 84-90 Link Here
84
     * @see Messager#printMessage(javax.tools.Diagnostic.Kind, CharSequence, Element, AnnotationMirror)
90
     * @see Messager#printMessage(javax.tools.Diagnostic.Kind, CharSequence, Element, AnnotationMirror)
85
     */
91
     */
86
    public LayerGenerationException(String message, Element erroneousElement, AnnotationMirror erroneousAnnotation) {
92
    public LayerGenerationException(String message, Element erroneousElement, AnnotationMirror erroneousAnnotation) {
87
        this(message, erroneousElement, erroneousAnnotation, null);
93
        this(message, erroneousElement, erroneousAnnotation, (AnnotationValue) null);
88
    }
94
    }
89
95
90
    /**
96
    /**
Lines 102-105 Link Here
102
        this.erroneousAnnotationValue = erroneousAnnotationValue;
108
        this.erroneousAnnotationValue = erroneousAnnotationValue;
103
    }
109
    }
104
110
111
    /**
112
     * An exception with an associated annotation.
113
     * Convenience constructor which locates an annotation on the erroneous element for you.
114
     * @param message a detail message which could be reported to the user
115
     * @param erroneousElement the associated element
116
     * @param processingEnv the processing environment passed to the processor
117
     * @param erroneousAnnotation the reflected annotation on the element (may be null as a convenience)
118
     * @see Messager#printMessage(javax.tools.Diagnostic.Kind, CharSequence, Element, AnnotationMirror)
119
     * @since 7.50
120
     */
121
    public LayerGenerationException(String message, Element erroneousElement, ProcessingEnvironment processingEnv,
122
            Annotation erroneousAnnotation) {
123
        this(message, erroneousElement, processingEnv, erroneousAnnotation, (String) null);
124
    }
125
126
    /**
127
     * An exception with an associated annotation value.
128
     * Convenience constructor which locates an annotation and its value on the erroneous element for you.
129
     * @param message a detail message which could be reported to the user
130
     * @param erroneousElement the associated element
131
     * @param processingEnv the processing environment passed to the processor
132
     * @param erroneousAnnotation the reflected annotation on the element (may be null as a convenience)
133
     * @param erroneousAnnotationMethod the name of a method in that annotation (may be null)
134
     * @see Messager#printMessage(javax.tools.Diagnostic.Kind, CharSequence, Element, AnnotationMirror, AnnotationValue)
135
     * @since 7.50
136
     */
137
    public LayerGenerationException(String message, Element erroneousElement, ProcessingEnvironment processingEnv,
138
            Annotation erroneousAnnotation, String erroneousAnnotationMethod) {
139
        super(message);
140
        this.erroneousElement = erroneousElement;
141
        if (erroneousAnnotation != null) {
142
            Class<? extends Annotation> clazz = null;
143
            Class<?> implClass = erroneousAnnotation.getClass();
144
            for (Class<?> xface : implClass.getInterfaces()) {
145
                if (xface.isAnnotation()) {
146
                    if (clazz == null) {
147
                        clazz = xface.asSubclass(Annotation.class);
148
                    } else {
149
                        throw new IllegalArgumentException(">1 annotation implemented by " + implClass.getName());
150
                    }
151
                }
152
            }
153
            if (clazz == null) {
154
                throw new IllegalArgumentException("no annotation implemented by " + implClass.getName());
155
            }
156
            if (erroneousAnnotationMethod != null) {
157
                try {
158
                    clazz.getMethod(erroneousAnnotationMethod);
159
                } catch (NoSuchMethodException x) {
160
                    throw new IllegalArgumentException("No such method " + erroneousAnnotationMethod + " in " + erroneousAnnotation);
161
                } catch (SecurityException x) {/* ignore? */}
162
            }
163
            this.erroneousAnnotation = findAnnotationMirror(erroneousElement, processingEnv, clazz);
164
            this.erroneousAnnotationValue = this.erroneousAnnotation != null && erroneousAnnotationMethod != null ?
165
                findAnnotationValue(this.erroneousAnnotation, erroneousAnnotationMethod) : null;
166
        } else {
167
            this.erroneousAnnotation = null;
168
            this.erroneousAnnotationValue = null;
169
        }
170
    }
171
172
    private static AnnotationMirror findAnnotationMirror(Element element, ProcessingEnvironment processingEnv, Class<? extends Annotation> annotation) {
173
        for (AnnotationMirror ann : element.getAnnotationMirrors()) {
174
            if (processingEnv.getElementUtils().getBinaryName((TypeElement) ann.getAnnotationType().asElement()).
175
                    contentEquals(annotation.getName())) {
176
                return ann;
177
            }
178
        }
179
        return null;
180
    }
181
182
    private AnnotationValue findAnnotationValue(AnnotationMirror annotation, String name) {
183
        for (Map.Entry<? extends ExecutableElement,? extends AnnotationValue> entry : annotation.getElementValues().entrySet()) {
184
            if (entry.getKey().getSimpleName().contentEquals(name)) {
185
                return entry.getValue();
186
            }
187
        }
188
        return null;
189
    }
190
105
}
191
}
(-)a/openide.filesystems/test/unit/src/org/openide/filesystems/annotations/LayerGenerationExceptionTest.java (+126 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 * <p/>
4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
5
 * <p/>
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 * <p/>
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common Development and
11
 * Distribution License("CDDL") (collectively, the "License"). You may not use
12
 * this file except in compliance with the License. You can obtain a copy of
13
 * the License at http://www.netbeans.org/cddl-gplv2.html or
14
 * nbbuild/licenses/CDDL-GPL-2-CP. See the License for the specific language
15
 * governing permissions and limitations under the License. When distributing
16
 * the software, include this License Header Notice in each file and include
17
 * the License file at nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
18
 * particular file as subject to the "Classpath" exception as provided by
19
 * Oracle in the GPL Version 2 section of the License file that accompanied
20
 * this code. If applicable, add the following below the License Header, with
21
 * the fields enclosed by brackets [] replaced by your own identifying
22
 * information: "Portions Copyrighted [year] [name of copyright owner]"
23
 * <p/>
24
 * If you wish your version of this file to be governed by only the CDDL or
25
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
26
 * elects to include this software in this distribution under the [CDDL or GPL
27
 * Version 2] license." If you do not indicate a single choice of license, a
28
 * recipient has the option to distribute your version of this file under
29
 * either the CDDL, the GPL Version 2 or to extend the choice of license to its
30
 * licensees as provided above. However, if you add GPL Version 2 code and
31
 * therefore, elected the GPL Version 2 license, then the option applies only
32
 * if the new code is made subject to such option by the copyright holder.
33
 * <p/>
34
 * Contributor(s):
35
 * <p/>
36
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
37
 */
38
39
package org.openide.filesystems.annotations;
40
41
import java.io.ByteArrayOutputStream;
42
import java.io.File;
43
import java.util.Arrays;
44
import java.util.HashSet;
45
import java.util.Set;
46
import javax.annotation.processing.Processor;
47
import javax.annotation.processing.RoundEnvironment;
48
import javax.annotation.processing.SupportedSourceVersion;
49
import javax.lang.model.SourceVersion;
50
import javax.lang.model.element.Element;
51
import javax.lang.model.element.TypeElement;
52
import javax.tools.Diagnostic.Kind;
53
import org.netbeans.junit.NbTestCase;
54
import org.openide.util.lookup.ServiceProvider;
55
import org.openide.util.test.AnnotationProcessorTestUtils;
56
57
public class LayerGenerationExceptionTest extends NbTestCase {
58
59
    public LayerGenerationExceptionTest(String name) {
60
        super(name);
61
    }
62
63
    public void testFindAnnotationMirror() throws Exception {
64
        File src = new File(getWorkDir(), "src");
65
        AnnotationProcessorTestUtils.makeSource(src, "p.C", "@" + A.class.getCanonicalName() + "(attr1=\"one\", attr2=\"two\") public class C {}");
66
        File dest = new File(getWorkDir(), "dest");
67
        ByteArrayOutputStream err = new ByteArrayOutputStream();
68
        assertTrue(AnnotationProcessorTestUtils.runJavac(src, null, dest, null, err));
69
        assertTrue(err.toString(), err.toString().contains("p.C two"));
70
    }
71
72
    /* XXX not yet implemented:
73
    public void testFindAnnotationMirrorNested() throws Exception {
74
        File src = new File(getWorkDir(), "src");
75
        AnnotationProcessorTestUtils.makeSource(src, "p.C",
76
                "@" + AS.class.getCanonicalName() + "({",
77
                "@" + A.class.getCanonicalName() + "(attr1=\"one\", attr2=\"two\"),",
78
                "@" + A.class.getCanonicalName() + "(attr1=\"three\", attr2=\"four\")",
79
                "})",
80
                "public class C {}");
81
        File dest = new File(getWorkDir(), "dest");
82
        ByteArrayOutputStream err = new ByteArrayOutputStream();
83
        boolean r = AnnotationProcessorTestUtils.runJavac(src, null, dest, null, err);
84
        String out = err.toString();
85
        assertTrue(out, r);
86
        assertTrue(out,out.contains("p.C two"));
87
        assertTrue(out,out.contains("p.C four"));
88
    }
89
    */
90
91
    public @interface A {
92
        String attr1();
93
        String attr2();
94
    }
95
96
    public @interface AS {
97
        A[] value();
98
    }
99
100
    @ServiceProvider(service=Processor.class)
101
    @SupportedSourceVersion(SourceVersion.RELEASE_6)
102
    public static class AP extends LayerGeneratingProcessor {
103
        public @Override Set<String> getSupportedAnnotationTypes() {
104
            return new HashSet<String>(Arrays.asList(A.class.getCanonicalName(), AS.class.getCanonicalName()));
105
        }
106
        protected @Override boolean handleProcess(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) throws LayerGenerationException {
107
            if (roundEnv.processingOver()) {
108
                return false;
109
            }
110
            for (Element e : roundEnv.getElementsAnnotatedWith(A.class)) {
111
                handle(e, e.getAnnotation(A.class));
112
            }
113
            for (Element e : roundEnv.getElementsAnnotatedWith(AS.class)) {
114
                for (A a : e.getAnnotation(AS.class).value()) {
115
                    handle(e, a);
116
                }
117
            }
118
            return true;
119
        }
120
        private void handle(Element e, A a) {
121
            LayerGenerationException lge = new LayerGenerationException("msg", e, processingEnv, a, "attr2");
122
            processingEnv.getMessager().printMessage(Kind.NOTE, lge.erroneousElement + " " + (lge.erroneousAnnotationValue != null ? lge.erroneousAnnotationValue.getValue() : null));
123
        }
124
    }
125
126
}
(-)a/openide.windows/src/org/netbeans/modules/openide/windows/TopComponentProcessor.java (-3 / +3 lines)
Lines 83-89 Link Here
83
            
83
            
84
            Description info = findInfo(e);
84
            Description info = findInfo(e);
85
            if (info == null) {
85
            if (info == null) {
86
                throw new LayerGenerationException("Cannot find TopComponent.Description for this element", e);
86
                throw new LayerGenerationException("Cannot find TopComponent.Description for this element", e, processingEnv, reg);
87
            }
87
            }
88
            String id = info.preferredID().replace('.', '-');
88
            String id = info.preferredID().replace('.', '-');
89
            
89
            
Lines 112-122 Link Here
112
                File actionFile = layer(e).
112
                File actionFile = layer(e).
113
                    file("Actions/" + aid.category() + "/" + aid.id().replace('.', '-') + ".instance").
113
                    file("Actions/" + aid.category() + "/" + aid.id().replace('.', '-') + ".instance").
114
                    methodvalue("instanceCreate", "org.openide.windows.TopComponent", "openAction");
114
                    methodvalue("instanceCreate", "org.openide.windows.TopComponent", "openAction");
115
                actionFile.instanceAttribute("component", TopComponent.class);
115
                actionFile.instanceAttribute("component", TopComponent.class, reg, null);
116
                if (reg.preferredID().length() > 0) {
116
                if (reg.preferredID().length() > 0) {
117
                    actionFile.stringvalue("preferredID", reg.preferredID());
117
                    actionFile.stringvalue("preferredID", reg.preferredID());
118
                }
118
                }
119
                actionFile.bundlevalue("displayName", reg.displayName());
119
                actionFile.bundlevalue("displayName", reg.displayName(), reg, "displayName");
120
                if (info != null && info.iconBase().length() > 0) {
120
                if (info != null && info.iconBase().length() > 0) {
121
                    actionFile.stringvalue("iconBase", info.iconBase());
121
                    actionFile.stringvalue("iconBase", info.iconBase());
122
                }
122
                }
(-)a/options.api/nbproject/project.xml (-1 / +1 lines)
Lines 120-126 Link Here
120
                    <build-prerequisite/>
120
                    <build-prerequisite/>
121
                    <compile-dependency/>
121
                    <compile-dependency/>
122
                    <run-dependency>
122
                    <run-dependency>
123
                        <specification-version>7.27</specification-version>
123
                        <specification-version>7.50</specification-version>
124
                    </run-dependency>
124
                    </run-dependency>
125
                </dependency>
125
                </dependency>
126
                <dependency>
126
                <dependency>
(-)a/options.api/src/org/netbeans/modules/options/OptionsPanelControllerProcessor.java (-14 / +15 lines)
Lines 44-49 Link Here
44
44
45
import java.io.FileNotFoundException;
45
import java.io.FileNotFoundException;
46
import java.io.IOException;
46
import java.io.IOException;
47
import java.lang.annotation.Annotation;
47
import java.util.Arrays;
48
import java.util.Arrays;
48
import java.util.HashSet;
49
import java.util.HashSet;
49
import java.util.Set;
50
import java.util.Set;
Lines 83-108 Link Here
83
        }
84
        }
84
        for (Element e : roundEnv.getElementsAnnotatedWith(TopLevelRegistration.class)) {
85
        for (Element e : roundEnv.getElementsAnnotatedWith(TopLevelRegistration.class)) {
85
            TopLevelRegistration r = e.getAnnotation(TopLevelRegistration.class);
86
            TopLevelRegistration r = e.getAnnotation(TopLevelRegistration.class);
86
            File file = layer(e).instanceFile("OptionsDialog", r.id().length() > 0 ? r.id() : null).
87
            File file = layer(e).instanceFile("OptionsDialog", r.id().length() > 0 ? r.id() : null, r, null).
87
                    methodvalue("instanceCreate", OptionsCategory.class.getName(), "createCategory").
88
                    methodvalue("instanceCreate", OptionsCategory.class.getName(), "createCategory").
88
                    instanceAttribute("controller", OptionsPanelController.class).
89
                    instanceAttribute("controller", OptionsPanelController.class).
89
                    bundlevalue("categoryName", r.categoryName()).
90
                    bundlevalue("categoryName", r.categoryName()).
90
                    position(r.position());
91
                    position(r.position());
91
            iconBase(e, r.iconBase(), file);
92
            iconBase(e, r.iconBase(), r, file);
92
            keywords(e, r.keywords(), r.keywordsCategory(), file);
93
            keywords(e, r.keywords(), r.keywordsCategory(), r, file);
93
            file.write();
94
            file.write();
94
        }
95
        }
95
        for (Element e : roundEnv.getElementsAnnotatedWith(SubRegistration.class)) {
96
        for (Element e : roundEnv.getElementsAnnotatedWith(SubRegistration.class)) {
96
            SubRegistration r = e.getAnnotation(SubRegistration.class);
97
            SubRegistration r = e.getAnnotation(SubRegistration.class);
97
            if (r.position() != Integer.MAX_VALUE && r.location().equals("Advanced")) {
98
            if (r.position() != Integer.MAX_VALUE && r.location().equals("Advanced")) {
98
                throw new LayerGenerationException("position ignored for Advanced subpanels", e);
99
                throw new LayerGenerationException("position ignored for Advanced subpanels", e, processingEnv, r, "position");
99
            }
100
            }
100
            File file = layer(e).instanceFile("OptionsDialog/" + r.location(), r.id().length() > 0 ? r.id() : null).
101
            File file = layer(e).instanceFile("OptionsDialog/" + r.location(), r.id().length() > 0 ? r.id() : null, r, null).
101
                    methodvalue("instanceCreate", AdvancedOption.class.getName(), "createSubCategory").
102
                    methodvalue("instanceCreate", AdvancedOption.class.getName(), "createSubCategory").
102
                    instanceAttribute("controller", OptionsPanelController.class).
103
                    instanceAttribute("controller", OptionsPanelController.class).
103
                    bundlevalue("displayName", r.displayName()).
104
                    bundlevalue("displayName", r.displayName()).
104
                    position(r.position());
105
                    position(r.position());
105
            keywords(e, r.keywords(), r.keywordsCategory(), file);
106
            keywords(e, r.keywords(), r.keywordsCategory(), r, file);
106
            file.write();
107
            file.write();
107
        }
108
        }
108
        for (Element e : roundEnv.getElementsAnnotatedWith(ContainerRegistration.class)) {
109
        for (Element e : roundEnv.getElementsAnnotatedWith(ContainerRegistration.class)) {
Lines 112-126 Link Here
112
                    stringvalue("advancedOptionsFolder", "OptionsDialog/" + r.id()).
113
                    stringvalue("advancedOptionsFolder", "OptionsDialog/" + r.id()).
113
                    bundlevalue("categoryName", r.categoryName()).
114
                    bundlevalue("categoryName", r.categoryName()).
114
                    position(r.position());
115
                    position(r.position());
115
            iconBase(e, r.iconBase(), file);
116
            iconBase(e, r.iconBase(), r, file);
116
            keywords(e, r.keywords(), r.keywordsCategory(), file);
117
            keywords(e, r.keywords(), r.keywordsCategory(), r, file);
117
            file.write();
118
            file.write();
118
            layer(e).folder("OptionsDialog/" + r.id()).position(0).write();
119
            layer(e).folder("OptionsDialog/" + r.id()).position(0).write();
119
        }
120
        }
120
        return true;
121
        return true;
121
    }
122
    }
122
123
123
    private void iconBase(Element e, String iconBase, File file) throws LayerGenerationException {
124
    private void iconBase(Element e, String iconBase, Annotation r, File file) throws LayerGenerationException {
124
        try { // XXX should probably be made a utility method in LayerBuilder
125
        try { // XXX should probably be made a utility method in LayerBuilder
125
            try {
126
            try {
126
                processingEnv.getFiler().getResource(StandardLocation.SOURCE_PATH, "", iconBase).openInputStream().close();
127
                processingEnv.getFiler().getResource(StandardLocation.SOURCE_PATH, "", iconBase).openInputStream().close();
Lines 132-151 Link Here
132
                }
133
                }
133
            }
134
            }
134
        } catch (IOException x) {
135
        } catch (IOException x) {
135
            throw new LayerGenerationException("Could not open " + iconBase + ": " + x, e);
136
            throw new LayerGenerationException("Could not open " + iconBase + ": " + x, e, processingEnv, r, "iconBase");
136
        }
137
        }
137
        file.stringvalue("iconBase", iconBase);
138
        file.stringvalue("iconBase", iconBase);
138
    }
139
    }
139
140
140
    private void keywords(Element e, String keywords, String keywordsCategory, File file) throws LayerGenerationException {
141
    private void keywords(Element e, String keywords, String keywordsCategory, Annotation r, File file) throws LayerGenerationException {
141
        if (keywords.length() > 0) {
142
        if (keywords.length() > 0) {
142
            if (keywordsCategory.length() == 0) {
143
            if (keywordsCategory.length() == 0) {
143
                throw new LayerGenerationException("Must specify both keywords and keywordsCategory", e);
144
                throw new LayerGenerationException("Must specify both keywords and keywordsCategory", e, processingEnv, r, "keywordsCategory");
144
            }
145
            }
145
            file.bundlevalue("keywords", keywords).bundlevalue("keywordsCategory", keywordsCategory);
146
            file.bundlevalue("keywords", keywords, r, "keywords").bundlevalue("keywordsCategory", keywordsCategory, r, "keywordsCategory");
146
        } else {
147
        } else {
147
            if (keywordsCategory.length() > 0) {
148
            if (keywordsCategory.length() > 0) {
148
                throw new LayerGenerationException("Must specify both keywords and keywordsCategory", e);
149
                throw new LayerGenerationException("Must specify both keywords and keywordsCategory", e, processingEnv, r, "keywords");
149
            }
150
            }
150
        }
151
        }
151
    }
152
    }
(-)a/project.ant/nbproject/project.xml (-1 / +1 lines)
Lines 139-145 Link Here
139
                    <build-prerequisite/>
139
                    <build-prerequisite/>
140
                    <compile-dependency/>
140
                    <compile-dependency/>
141
                    <run-dependency>
141
                    <run-dependency>
142
                        <specification-version>7.19</specification-version>
142
                        <specification-version>7.50</specification-version>
143
                    </run-dependency>
143
                    </run-dependency>
144
                </dependency>
144
                </dependency>
145
                <dependency>
145
                <dependency>
(-)a/project.ant/src/org/netbeans/modules/project/ant/AntBasedProcessor.java (-6 / +6 lines)
Lines 95-104 Link Here
95
                    name = classname.replace('.', '-');
95
                    name = classname.replace('.', '-');
96
                    methodname = null;
96
                    methodname = null;
97
                    if (!e.getModifiers().contains(Modifier.PUBLIC)) {
97
                    if (!e.getModifiers().contains(Modifier.PUBLIC)) {
98
                        throw new LayerGenerationException("Class needs to be public"); // NOI18N
98
                        throw new LayerGenerationException("Class needs to be public", e, processingEnv, reg); // NOI18N
99
                    }
99
                    }
100
                    if (!processingEnv.getTypeUtils().isAssignable(e.asType(), project)) {
100
                    if (!processingEnv.getTypeUtils().isAssignable(e.asType(), project)) {
101
                        throw new LayerGenerationException("Class needs to extend Project"); // NOI18N
101
                        throw new LayerGenerationException("Class needs to extend Project", e, processingEnv, reg); // NOI18N
102
                    }
102
                    }
103
                    boolean found = false;
103
                    boolean found = false;
104
                    for (Element cns : processingEnv.getElementUtils().getAllMembers((TypeElement)e)) {
104
                    for (Element cns : processingEnv.getElementUtils().getAllMembers((TypeElement)e)) {
Lines 118-124 Link Here
118
                        }
118
                        }
119
                    }
119
                    }
120
                    if (!found) {
120
                    if (!found) {
121
                        throw new LayerGenerationException("There needs to be public constructor taking AntProjectHelper parameter"); // NOI18N
121
                        throw new LayerGenerationException("There needs to be public constructor taking AntProjectHelper parameter", e, processingEnv, reg); // NOI18N
122
                    }
122
                    }
123
123
124
                    break;
124
                    break;
Lines 128-134 Link Here
128
                    name = (classname + "." + methodname).replace('.', '-');
128
                    name = (classname + "." + methodname).replace('.', '-');
129
                    
129
                    
130
                    if (!e.getEnclosingElement().getModifiers().contains(Modifier.PUBLIC)) {
130
                    if (!e.getEnclosingElement().getModifiers().contains(Modifier.PUBLIC)) {
131
                        throw new LayerGenerationException("Class needs to be public"); // NOI18N
131
                        throw new LayerGenerationException("Class needs to be public", e, processingEnv, reg); // NOI18N
132
                    }
132
                    }
133
133
134
                    ExecutableElement exec = (ExecutableElement)e;
134
                    ExecutableElement exec = (ExecutableElement)e;
Lines 138-147 Link Here
138
                        exec.getParameters().size() != 1 ||
138
                        exec.getParameters().size() != 1 ||
139
                        !exec.getParameters().get(0).asType().equals(antHelper)
139
                        !exec.getParameters().get(0).asType().equals(antHelper)
140
                    ) {
140
                    ) {
141
                        throw new LayerGenerationException("The method needs to be public, static and take AntProjectHelper argument"); // NOI18N
141
                        throw new LayerGenerationException("The method needs to be public, static and take AntProjectHelper argument", e, processingEnv, reg); // NOI18N
142
                    }
142
                    }
143
                    if (!processingEnv.getTypeUtils().isAssignable(exec.getReturnType(), project)) {
143
                    if (!processingEnv.getTypeUtils().isAssignable(exec.getReturnType(), project)) {
144
                        throw new LayerGenerationException("Method needs to return Project"); // NOI18N
144
                        throw new LayerGenerationException("Method needs to return Project", e, processingEnv, reg); // NOI18N
145
                    }
145
                    }
146
146
147
                    break;
147
                    break;
(-)a/projectapi/nbproject/project.xml (-1 / +1 lines)
Lines 63-69 Link Here
63
                    <build-prerequisite/>
63
                    <build-prerequisite/>
64
                    <compile-dependency/>
64
                    <compile-dependency/>
65
                    <run-dependency>
65
                    <run-dependency>
66
                        <specification-version>6.2</specification-version>
66
                        <specification-version>7.50</specification-version>
67
                    </run-dependency>
67
                    </run-dependency>
68
                </dependency>
68
                </dependency>
69
                <dependency>
69
                <dependency>
(-)a/projectapi/src/org/netbeans/modules/projectapi/LookupProviderAnnotationProcessor.java (-20 / +20 lines)
Lines 96-127 Link Here
96
        for (Element e : roundEnv.getElementsAnnotatedWith(LookupProvider.Registration.class)) {
96
        for (Element e : roundEnv.getElementsAnnotatedWith(LookupProvider.Registration.class)) {
97
            LookupProvider.Registration lpr = e.getAnnotation(LookupProvider.Registration.class);
97
            LookupProvider.Registration lpr = e.getAnnotation(LookupProvider.Registration.class);
98
            if (lpr.projectType().length == 0 && lpr.projectTypes().length == 0) {
98
            if (lpr.projectType().length == 0 && lpr.projectTypes().length == 0) {
99
                throw new LayerGenerationException("You must specify either projectType or projectTypes", e);
99
                throw new LayerGenerationException("You must specify either projectType or projectTypes", e, processingEnv, lpr);
100
            }
100
            }
101
            for (String type : lpr.projectType()) {
101
            for (String type : lpr.projectType()) {
102
                layer(e).instanceFile("Projects/" + type + "/Lookup", null, LookupProvider.class).write();
102
                layer(e).instanceFile("Projects/" + type + "/Lookup", null, LookupProvider.class, lpr, null).write();
103
            }
103
            }
104
            for (LookupProvider.Registration.ProjectType type : lpr.projectTypes()) {
104
            for (LookupProvider.Registration.ProjectType type : lpr.projectTypes()) {
105
                layer(e).instanceFile("Projects/" + type.id() + "/Lookup", null, LookupProvider.class).position(type.position()).write();
105
                layer(e).instanceFile("Projects/" + type.id() + "/Lookup", null, LookupProvider.class, type, null).position(type.position()).write();
106
            }
106
            }
107
        }
107
        }
108
        for (Element e : roundEnv.getElementsAnnotatedWith(ProjectServiceProvider.class)) {
108
        for (Element e : roundEnv.getElementsAnnotatedWith(ProjectServiceProvider.class)) {
109
            ProjectServiceProvider psp = e.getAnnotation(ProjectServiceProvider.class);
109
            List<TypeMirror> services = findServiceAnnotation(e);
110
            List<TypeMirror> services = findServiceAnnotation(e);
110
            if (services.isEmpty()) {
111
            if (services.isEmpty()) {
111
                throw new LayerGenerationException("Must specify at least one service", e);
112
                throw new LayerGenerationException("Must specify at least one service", e, processingEnv, psp);
112
            }
113
            }
113
            String servicesBinName = null;
114
            String servicesBinName = null;
114
            for (TypeMirror service : services) {
115
            for (TypeMirror service : services) {
115
                String n = processingEnv.getElementUtils().getBinaryName((TypeElement) processingEnv.getTypeUtils().asElement(service)).toString();
116
                String n = processingEnv.getElementUtils().getBinaryName((TypeElement) processingEnv.getTypeUtils().asElement(service)).toString();
116
                if (n.equals(LookupMerger.class.getName())) {
117
                if (n.equals(LookupMerger.class.getName())) {
117
                    throw new LayerGenerationException("@ProjectServiceProvider should not be used on LookupMerger; use @LookupMerger.Registration instead", e);
118
                    throw new LayerGenerationException("@ProjectServiceProvider should not be used on LookupMerger; use @LookupMerger.Registration instead", e, processingEnv, psp);
118
                }
119
                }
119
                servicesBinName = servicesBinName == null ? n : servicesBinName + "," + n;
120
                servicesBinName = servicesBinName == null ? n : servicesBinName + "," + n;
120
            }
121
            }
121
            String[] binAndMethodNames = findPSPDefinition(e, services);
122
            String[] binAndMethodNames = findPSPDefinition(e, services, psp);
122
            ProjectServiceProvider psp = e.getAnnotation(ProjectServiceProvider.class);
123
            if (psp.projectType().length == 0 && psp.projectTypes().length == 0) {
123
            if (psp.projectType().length == 0 && psp.projectTypes().length == 0) {
124
                throw new LayerGenerationException("You must specify either projectType or projectTypes", e);
124
                throw new LayerGenerationException("You must specify either projectType or projectTypes", e, processingEnv, psp);
125
            }
125
            }
126
            String fileBaseName = binAndMethodNames[0].replace('.', '-');
126
            String fileBaseName = binAndMethodNames[0].replace('.', '-');
127
            if (binAndMethodNames[1] != null) {
127
            if (binAndMethodNames[1] != null) {
Lines 163-173 Link Here
163
            }
163
            }
164
            DeclaredType service = findLookupMergerType(impl);
164
            DeclaredType service = findLookupMergerType(impl);
165
            if (service == null) {
165
            if (service == null) {
166
                throw new LayerGenerationException("Not assignable to LookupMerger<T> for some T", e);
166
                throw new LayerGenerationException("Not assignable to LookupMerger<T> for some T", e, processingEnv, lmr);
167
            }
167
            }
168
            String serviceBinName = processingEnv.getElementUtils().getBinaryName((TypeElement) service.asElement()).toString();
168
            String serviceBinName = processingEnv.getElementUtils().getBinaryName((TypeElement) service.asElement()).toString();
169
            if (lmr.projectType().length == 0 && lmr.projectTypes().length == 0) {
169
            if (lmr.projectType().length == 0 && lmr.projectTypes().length == 0) {
170
                throw new LayerGenerationException("You must specify either projectType or projectTypes", e);
170
                throw new LayerGenerationException("You must specify either projectType or projectTypes", e, processingEnv, lmr);
171
            }
171
            }
172
            for (String type : lmr.projectType()) {
172
            for (String type : lmr.projectType()) {
173
                layer(e).file("Projects/" + type + "/Lookup/" + fileBaseName + ".instance").
173
                layer(e).file("Projects/" + type + "/Lookup/" + fileBaseName + ".instance").
Lines 208-219 Link Here
208
        throw new LayerGenerationException("No @ProjectServiceProvider found", e);
208
        throw new LayerGenerationException("No @ProjectServiceProvider found", e);
209
    }
209
    }
210
210
211
    private String[] findPSPDefinition(Element e, List<TypeMirror> services) throws LayerGenerationException {
211
    private String[] findPSPDefinition(Element e, List<TypeMirror> services, ProjectServiceProvider psp) throws LayerGenerationException {
212
        if (e.getKind() == ElementKind.CLASS) {
212
        if (e.getKind() == ElementKind.CLASS) {
213
            TypeElement clazz = (TypeElement) e;
213
            TypeElement clazz = (TypeElement) e;
214
            for (TypeMirror service : services) {
214
            for (TypeMirror service : services) {
215
                if (!processingEnv.getTypeUtils().isAssignable(clazz.asType(), service)) {
215
                if (!processingEnv.getTypeUtils().isAssignable(clazz.asType(), service)) {
216
                    throw new LayerGenerationException("Not assignable to " + service, e);
216
                    throw new LayerGenerationException("Not assignable to " + service, e, processingEnv, psp);
217
                }
217
                }
218
            }
218
            }
219
            int constructorCount = 0;
219
            int constructorCount = 0;
Lines 234-270 Link Here
234
                constructorCount++;
234
                constructorCount++;
235
            }
235
            }
236
            if (constructorCount != 1) {
236
            if (constructorCount != 1) {
237
                throw new LayerGenerationException("Must have exactly one public constructor optionally taking Project and/or Lookup", e);
237
                throw new LayerGenerationException("Must have exactly one public constructor optionally taking Project and/or Lookup", e, processingEnv, psp);
238
            }
238
            }
239
            if (!clazz.getModifiers().contains(Modifier.PUBLIC)) {
239
            if (!clazz.getModifiers().contains(Modifier.PUBLIC)) {
240
                throw new LayerGenerationException("Class must be public", e);
240
                throw new LayerGenerationException("Class must be public", e, processingEnv, psp);
241
            }
241
            }
242
            return new String[] {processingEnv.getElementUtils().getBinaryName(clazz).toString(), null};
242
            return new String[] {processingEnv.getElementUtils().getBinaryName(clazz).toString(), null};
243
        } else {
243
        } else {
244
            ExecutableElement meth = (ExecutableElement) e;
244
            ExecutableElement meth = (ExecutableElement) e;
245
            for (TypeMirror service : services) {
245
            for (TypeMirror service : services) {
246
                if (!processingEnv.getTypeUtils().isAssignable(meth.getReturnType(), service)) {
246
                if (!processingEnv.getTypeUtils().isAssignable(meth.getReturnType(), service)) {
247
                    throw new LayerGenerationException("Not assignable to " + service, e);
247
                    throw new LayerGenerationException("Not assignable to " + service, e, processingEnv, psp);
248
                }
248
                }
249
            }
249
            }
250
            if (!meth.getModifiers().contains(Modifier.PUBLIC)) {
250
            if (!meth.getModifiers().contains(Modifier.PUBLIC)) {
251
                throw new LayerGenerationException("Method must be public", e);
251
                throw new LayerGenerationException("Method must be public", e, processingEnv, psp);
252
            }
252
            }
253
            if (!meth.getModifiers().contains(Modifier.STATIC)) {
253
            if (!meth.getModifiers().contains(Modifier.STATIC)) {
254
                throw new LayerGenerationException("Method must be static", e);
254
                throw new LayerGenerationException("Method must be static", e, processingEnv, psp);
255
            }
255
            }
256
            List<? extends VariableElement> params = meth.getParameters();
256
            List<? extends VariableElement> params = meth.getParameters();
257
            if (params.size() > 2) {
257
            if (params.size() > 2) {
258
                throw new LayerGenerationException("Method must take at most two parameters", e);
258
                throw new LayerGenerationException("Method must take at most two parameters", e, processingEnv, psp);
259
            }
259
            }
260
            for (VariableElement param : params) {
260
            for (VariableElement param : params) {
261
                if (!param.asType().equals(processingEnv.getElementUtils().getTypeElement(Project.class.getCanonicalName()).asType()) &&
261
                if (!param.asType().equals(processingEnv.getElementUtils().getTypeElement(Project.class.getCanonicalName()).asType()) &&
262
                        !param.asType().equals(processingEnv.getElementUtils().getTypeElement(Lookup.class.getCanonicalName()).asType())) {
262
                        !param.asType().equals(processingEnv.getElementUtils().getTypeElement(Lookup.class.getCanonicalName()).asType())) {
263
                    throw new LayerGenerationException("Method parameters may be either Lookup or Project", e);
263
                    throw new LayerGenerationException("Method parameters may be either Lookup or Project", e, processingEnv, psp);
264
                }
264
                }
265
            }
265
            }
266
            if (!meth.getEnclosingElement().getModifiers().contains(Modifier.PUBLIC)) {
266
            if (!meth.getEnclosingElement().getModifiers().contains(Modifier.PUBLIC)) {
267
                throw new LayerGenerationException("Class must be public", e);
267
                throw new LayerGenerationException("Class must be public", e, processingEnv, psp);
268
            }
268
            }
269
            return new String[] {
269
            return new String[] {
270
                processingEnv.getElementUtils().getBinaryName((TypeElement) meth.getEnclosingElement()).toString(),
270
                processingEnv.getElementUtils().getBinaryName((TypeElement) meth.getEnclosingElement()).toString(),
(-)a/projectuiapi/nbproject/project.xml (-1 / +1 lines)
Lines 114-120 Link Here
114
                    <build-prerequisite/>
114
                    <build-prerequisite/>
115
                    <compile-dependency/>
115
                    <compile-dependency/>
116
                    <run-dependency>
116
                    <run-dependency>
117
                        <specification-version>7.26</specification-version>
117
                        <specification-version>7.50</specification-version>
118
                    </run-dependency>
118
                    </run-dependency>
119
                </dependency>
119
                </dependency>
120
                <dependency>
120
                <dependency>
(-)a/projectuiapi/src/org/netbeans/modules/project/uiapi/CompositeCategoryProviderAnnotationProcessor.java (-4 / +4 lines)
Lines 97-106 Link Here
97
        }
97
        }
98
        if (e.getKind() == ElementKind.PACKAGE) {
98
        if (e.getKind() == ElementKind.PACKAGE) {
99
            if (!addsFolder) {
99
            if (!addsFolder) {
100
                throw new LayerGenerationException("Must specify categoryLabel", e);
100
                throw new LayerGenerationException("Must specify categoryLabel", e, processingEnv, r);
101
            }
101
            }
102
        } else {
102
        } else {
103
            File f = layer(e).instanceFile(path, addsFolder ? "Self" : null, CompositeCategoryProvider.class);
103
            File f = layer(e).instanceFile(path, addsFolder ? "Self" : null, CompositeCategoryProvider.class, r, null);
104
            f.position(addsFolder ? 0 : r.position());
104
            f.position(addsFolder ? 0 : r.position());
105
            f.write();
105
            f.write();
106
        }
106
        }
Lines 108-116 Link Here
108
108
109
    private void handleFolder(String path, Element e, Registration r) throws LayerGenerationException {
109
    private void handleFolder(String path, Element e, Registration r) throws LayerGenerationException {
110
        if (r.category().length() == 0) {
110
        if (r.category().length() == 0) {
111
            throw new LayerGenerationException("Must specify category", e);
111
            throw new LayerGenerationException("Must specify category", e, processingEnv, r);
112
        }
112
        }
113
        layer(e).folder(path).bundlevalue("displayName", r.categoryLabel()).position(r.position()).write();
113
        layer(e).folder(path).bundlevalue("displayName", r.categoryLabel(), r, "categoryLabel").position(r.position()).write();
114
    }
114
    }
115
115
116
}
116
}
(-)a/projectuiapi/src/org/netbeans/modules/project/uiapi/NodeFactoryAnnotationProcessor.java (-4 / +4 lines)
Lines 73-82 Link Here
73
            return false;
73
            return false;
74
        }
74
        }
75
        for (Element e : roundEnv.getElementsAnnotatedWith(NodeFactory.Registration.class)) {
75
        for (Element e : roundEnv.getElementsAnnotatedWith(NodeFactory.Registration.class)) {
76
            NodeFactory.Registration lpr = e.getAnnotation(NodeFactory.Registration.class);
76
            NodeFactory.Registration r = e.getAnnotation(NodeFactory.Registration.class);
77
            for (String type : lpr.projectType()) {
77
            for (String type : r.projectType()) {
78
                layer(e).instanceFile("Projects/" + type + "/Nodes", null, NodeFactory.class). //NOI18N
78
                layer(e).instanceFile("Projects/" + type + "/Nodes", null, NodeFactory.class, r, null). //NOI18N
79
                        position(lpr.position()).write();
79
                        position(r.position()).write();
80
            }
80
            }
81
        }
81
        }
82
        return true;
82
        return true;
(-)a/settings/nbproject/project.xml (-1 / +1 lines)
Lines 88-94 Link Here
88
                    <build-prerequisite/>
88
                    <build-prerequisite/>
89
                    <compile-dependency/>
89
                    <compile-dependency/>
90
                    <run-dependency>
90
                    <run-dependency>
91
                        <specification-version>7.49</specification-version>
91
                        <specification-version>7.50</specification-version>
92
                    </run-dependency>
92
                    </run-dependency>
93
                </dependency>
93
                </dependency>
94
                <dependency>
94
                <dependency>
(-)a/settings/src/org/netbeans/modules/settings/convertors/ConvertorProcessor.java (-8 / +9 lines)
Lines 44-49 Link Here
44
44
45
package org.netbeans.modules.settings.convertors;
45
package org.netbeans.modules.settings.convertors;
46
46
47
import java.lang.annotation.Annotation;
47
import java.util.Arrays;
48
import java.util.Arrays;
48
import java.util.HashSet;
49
import java.util.HashSet;
49
import java.util.Set;
50
import java.util.Set;
Lines 93-99 Link Here
93
        for (Element e : env.getElementsAnnotatedWith(ConvertAsProperties.class)) {
94
        for (Element e : env.getElementsAnnotatedWith(ConvertAsProperties.class)) {
94
            ConvertAsProperties reg = e.getAnnotation(ConvertAsProperties.class);
95
            ConvertAsProperties reg = e.getAnnotation(ConvertAsProperties.class);
95
96
96
            String convElem = instantiableClassOrMethod(e, true);
97
            String convElem = instantiableClassOrMethod(e, true, reg);
97
            final String dtd = reg.dtd();
98
            final String dtd = reg.dtd();
98
99
99
            String dtdCode = convertPublicId(dtd);
100
            String dtdCode = convertPublicId(dtd);
Lines 146-152 Link Here
146
147
147
        for (Element e : env.getElementsAnnotatedWith(ConvertAsJavaBean.class)) {
148
        for (Element e : env.getElementsAnnotatedWith(ConvertAsJavaBean.class)) {
148
            ConvertAsJavaBean reg = e.getAnnotation(ConvertAsJavaBean.class);
149
            ConvertAsJavaBean reg = e.getAnnotation(ConvertAsJavaBean.class);
149
            String convElem = instantiableClassOrMethod(e, false);
150
            String convElem = instantiableClassOrMethod(e, false, reg);
150
            File f = layer(e).file("xml/memory/" + convElem.replace('.', '/'));
151
            File f = layer(e).file("xml/memory/" + convElem.replace('.', '/'));
151
            f.stringvalue("settings.providerPath", "xml/lookups/NetBeans/DTD_XML_beans_1_0.instance");
152
            f.stringvalue("settings.providerPath", "xml/lookups/NetBeans/DTD_XML_beans_1_0.instance");
152
            if (reg.subclasses()) {
153
            if (reg.subclasses()) {
Lines 228-239 Link Here
228
        return f.stringvalue("xmlproperties.ignoreChanges", sb.toString());
229
        return f.stringvalue("xmlproperties.ignoreChanges", sb.toString());
229
    }
230
    }
230
231
231
    private String instantiableClassOrMethod(Element e, boolean checkMethods) throws IllegalArgumentException, LayerGenerationException {
232
    private String instantiableClassOrMethod(Element e, boolean checkMethods, Annotation r) throws IllegalArgumentException, LayerGenerationException {
232
        switch (e.getKind()) {
233
        switch (e.getKind()) {
233
            case CLASS: {
234
            case CLASS: {
234
                String clazz = processingEnv.getElementUtils().getBinaryName((TypeElement) e).toString();
235
                String clazz = processingEnv.getElementUtils().getBinaryName((TypeElement) e).toString();
235
                if (e.getModifiers().contains(Modifier.ABSTRACT)) {
236
                if (e.getModifiers().contains(Modifier.ABSTRACT)) {
236
                    throw new LayerGenerationException(clazz + " must not be abstract", e);
237
                    throw new LayerGenerationException(clazz + " must not be abstract", e, processingEnv, r);
237
                }
238
                }
238
                {
239
                {
239
                    boolean hasDefaultCtor = false;
240
                    boolean hasDefaultCtor = false;
Lines 244-250 Link Here
244
                        }
245
                        }
245
                    }
246
                    }
246
                    if (!hasDefaultCtor) {
247
                    if (!hasDefaultCtor) {
247
                        throw new LayerGenerationException(clazz + " must have a no-argument constructor", e);
248
                        throw new LayerGenerationException(clazz + " must have a no-argument constructor", e, processingEnv, r);
248
                    }
249
                    }
249
                }
250
                }
250
                if (checkMethods) {
251
                if (checkMethods) {
Lines 270-285 Link Here
270
                        }
271
                        }
271
                    }
272
                    }
272
                    if (!hasRead) {
273
                    if (!hasRead) {
273
                        throw new LayerGenerationException(clazz + " must have proper readProperties method", e);
274
                        throw new LayerGenerationException(clazz + " must have proper readProperties method", e, processingEnv, r);
274
                    }
275
                    }
275
                    if (!hasWrite) {
276
                    if (!hasWrite) {
276
                        throw new LayerGenerationException(clazz + " must have proper writeProperties method", e);
277
                        throw new LayerGenerationException(clazz + " must have proper writeProperties method", e, processingEnv, r);
277
                    }
278
                    }
278
                }
279
                }
279
                return clazz;
280
                return clazz;
280
            }
281
            }
281
            default:
282
            default:
282
                throw new LayerGenerationException("Annotated element is not loadable as an instance: " + e);
283
                throw new LayerGenerationException("Annotated element is not loadable as an instance", e, processingEnv, r);
283
        }
284
        }
284
    }
285
    }
285
}
286
}

Return to bug 194545