--- a/maven/src/org/netbeans/modules/maven/nodes/DependencyNode.java +++ a/maven/src/org/netbeans/modules/maven/nodes/DependencyNode.java @@ -117,6 +117,7 @@ import org.openide.filesystems.URLMapper; import org.openide.loaders.DataObject; import org.openide.loaders.DataObjectNotFoundException; +import org.openide.modules.StaticResource; import org.openide.nodes.AbstractNode; import org.openide.nodes.Children; import org.openide.nodes.FilterNode; @@ -139,9 +140,15 @@ * @author Milos Kleint */ public class DependencyNode extends AbstractNode implements PreferenceChangeListener { - private static final String JAVADOC_BADGE_ICON = "org/netbeans/modules/maven/DependencyJavadocIncluded.png"; //NOI18N - private static final String SOURCE_BADGE_ICON = "org/netbeans/modules/maven/DependencySrcIncluded.png"; //NOI18N - private static final String MANAGED_BADGE_ICON = "org/netbeans/modules/maven/DependencyManaged.png"; //NOI18N + private static final @StaticResource String JAVADOC_BADGE_ICON = "org/netbeans/modules/maven/DependencyJavadocIncluded.png"; //NOI18N + private static final @StaticResource String SOURCE_BADGE_ICON = "org/netbeans/modules/maven/DependencySrcIncluded.png"; //NOI18N + private static final @StaticResource String MANAGED_BADGE_ICON = "org/netbeans/modules/maven/DependencyManaged.png"; //NOI18N + private static final @StaticResource String ARTIFACT_ICON = "org/netbeans/modules/maven/ArtifactIcon.png"; + private static final @StaticResource String DEPENDENCY_ICON = "org/netbeans/modules/maven/DependencyIcon.png"; + private static final @StaticResource String MAVEN_ICON = "org/netbeans/modules/maven/resources/Maven2Icon.gif"; + private static final @StaticResource String TRANSITIVE_ARTIFACT_ICON = "org/netbeans/modules/maven/TransitiveArtifactIcon.png"; + private static final @StaticResource String TRANSITIVE_DEPENDENCY_ICON = "org/netbeans/modules/maven/TransitiveDependencyIcon.png"; + private static final @StaticResource String TRANSITIVE_MAVEN_ICON = "org/netbeans/modules/maven/TransitiveMaven2Icon.gif"; private Artifact art; private NbMavenProjectImpl project; @@ -235,20 +242,20 @@ private void setIconBase(boolean longLiving) { if (longLiving && isDependencyProjectAvailable()) { if (isTransitive()) { - setIconBaseWithExtension("org/netbeans/modules/maven/TransitiveMaven2Icon.gif"); //NOI18N + setIconBaseWithExtension(TRANSITIVE_MAVEN_ICON); } else { - setIconBaseWithExtension("org/netbeans/modules/maven/resources/Maven2Icon.gif"); //NOI18N + setIconBaseWithExtension(MAVEN_ICON); } } else if (isTransitive()) { if (isAddedToCP()) { - setIconBaseWithExtension("org/netbeans/modules/maven/TransitiveDependencyIcon.png"); //NOI18N + setIconBaseWithExtension(TRANSITIVE_DEPENDENCY_ICON); } else { - setIconBaseWithExtension("org/netbeans/modules/maven/TransitiveArtifactIcon.png"); //NOI18N + setIconBaseWithExtension(TRANSITIVE_ARTIFACT_ICON); } - } else if (isAddedToCP()) { //NOI18N - setIconBaseWithExtension("org/netbeans/modules/maven/DependencyIcon.png"); //NOI18N + } else if (isAddedToCP()) { + setIconBaseWithExtension(DEPENDENCY_ICON); } else { - setIconBaseWithExtension("org/netbeans/modules/maven/ArtifactIcon.png"); //NOI18N + setIconBaseWithExtension(ARTIFACT_ICON); } } --- a/openide.modules/apichanges.xml +++ a/openide.modules/apichanges.xml @@ -50,6 +50,21 @@ Modules API + + + Added StaticResource + + + + + +

+ Introduced an annotation for validating the existence of static resources. +

+
+ + +
Added Places --- a/openide.modules/manifest.mf +++ a/openide.modules/manifest.mf @@ -1,5 +1,5 @@ Manifest-Version: 1.0 OpenIDE-Module: org.openide.modules OpenIDE-Module-Localizing-Bundle: org/openide/modules/Bundle.properties -OpenIDE-Module-Specification-Version: 7.28 +OpenIDE-Module-Specification-Version: 7.29 --- a/openide.modules/src/org/netbeans/modules/openide/modules/StaticResourceProcessor.java +++ a/openide.modules/src/org/netbeans/modules/openide/modules/StaticResourceProcessor.java @@ -0,0 +1,138 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2011 Sun Microsystems, Inc. + */ + +package org.netbeans.modules.openide.modules; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Collections; +import java.util.Set; +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.Processor; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedSourceVersion; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.tools.Diagnostic; +import javax.tools.JavaFileManager; +import javax.tools.StandardLocation; +import org.openide.modules.StaticResource; +import org.openide.util.lookup.ServiceProvider; + +@ServiceProvider(service=Processor.class) +@SupportedSourceVersion(SourceVersion.RELEASE_6) +public class StaticResourceProcessor extends AbstractProcessor { + + public @Override Set getSupportedAnnotationTypes() { + return Collections.singleton(StaticResource.class.getCanonicalName()); + } + + @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { + if (!roundEnv.processingOver()) { + for (Element e : roundEnv.getElementsAnnotatedWith(StaticResource.class)) { + StaticResource sr = e.getAnnotation(StaticResource.class); + if (sr == null) { + continue; + } + Object v = ((VariableElement) e).getConstantValue(); + if (!(v instanceof String)) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@StaticResource may only be used on a String constant", e); + continue; + } + String resource = (String) v; + // remainder adapted from LayerBuilder, but cannot reference that here + if (sr.relative()) { + try { + resource = new URI(null, findPackage(e).replace('.', '/') + "/", null).resolve(new URI(null, resource, null)).getPath(); + } catch (URISyntaxException x) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, x.getMessage(), e); + continue; + } + } + if (resource.startsWith("/")) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "do not use leading slashes on resource paths", e); + continue; + } + if (sr.searchClasspath()) { + boolean ok = false; + for (JavaFileManager.Location loc : new JavaFileManager.Location[] {StandardLocation.SOURCE_PATH, /* #181355 */ StandardLocation.CLASS_OUTPUT, StandardLocation.CLASS_PATH, StandardLocation.PLATFORM_CLASS_PATH}) { + try { + processingEnv.getFiler().getResource(loc, "", resource); + ok = true; + } catch (IOException ex) { + continue; + } + } + if (!ok) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "cannot find resource " + resource, e); + } + } else { + try { + try { + processingEnv.getFiler().getResource(StandardLocation.SOURCE_PATH, "", resource).openInputStream().close(); + } catch (FileNotFoundException x) { + processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", resource).openInputStream().close(); + } + } catch (IOException x) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "cannot find resource " + resource, e); + } + } + } + } + return true; + } + + private static String findPackage(Element e) { + switch (e.getKind()) { + case PACKAGE: + return ((PackageElement) e).getQualifiedName().toString(); + default: + return findPackage(e.getEnclosingElement()); + } + } + +} --- a/openide.modules/src/org/openide/modules/StaticResource.java +++ a/openide.modules/src/org/openide/modules/StaticResource.java @@ -0,0 +1,79 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2011 Sun Microsystems, Inc. + */ + +package org.openide.modules; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.openide.util.ImageUtilities; + +/** + * Marker for a constant representing a static resource. + * The annotated field must be a compile-time {@code String} constant whose value denotes a resource path. + * For example, the resource might be an icon path intended for {@link ImageUtilities#loadImage(String)}. + * The primary purpose of the annotation is for its processor, which will signal a compile-time error + * if the resource does not in fact exist - ensuring that at least this usage will not be accidentally + * broken by moving, renaming, or deleting the resource. + * @since 7.29 + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.SOURCE) +@Documented +public @interface StaticResource { + + /** + * If true, permit the resource to be in the classpath. + * By default, it may only be in the sourcepath. + */ + boolean searchClasspath() default false; + + /** + * If true, consider the resource path to be relative to the current package. + * ({@code ../} sequences are permitted.) + * By default, it must be an absolute path (not starting with {@code /}). + */ + boolean relative() default false; + +}