Introducing meta-annotation to create Registration annotation for mime-lookup registration. diff --git a/editor.mimelookup/apichanges.xml b/editor.mimelookup/apichanges.xml --- a/editor.mimelookup/apichanges.xml +++ b/editor.mimelookup/apichanges.xml @@ -108,6 +108,19 @@ + + @MimeLocation, @MimeRegistration and @MimeRegistrations added + + + + + + Added @MimeLocation, @MimeRegistration and @MimeRegistrations + that allow to register services to the MimeLookup. + + + + MimeLookup.getLookup(String mimePath) method added diff --git a/editor.mimelookup/manifest.mf b/editor.mimelookup/manifest.mf --- a/editor.mimelookup/manifest.mf +++ b/editor.mimelookup/manifest.mf @@ -1,7 +1,7 @@ Manifest-Version: 1.0 OpenIDE-Module: org.netbeans.modules.editor.mimelookup/1 OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/editor/mimelookup/Bundle.properties -OpenIDE-Module-Specification-Version: 1.18 +OpenIDE-Module-Specification-Version: 1.19 OpenIDE-Module-Recommends: org.netbeans.spi.editor.mimelookup.MimeDataProvider AutoUpdate-Essential-Module: true diff --git a/editor.mimelookup/nbproject/project.xml b/editor.mimelookup/nbproject/project.xml --- a/editor.mimelookup/nbproject/project.xml +++ b/editor.mimelookup/nbproject/project.xml @@ -101,6 +101,11 @@ + + org.openide.util.lookup + + + diff --git a/editor.mimelookup/src/org/netbeans/api/editor/mimelookup/MimeRegistration.java b/editor.mimelookup/src/org/netbeans/api/editor/mimelookup/MimeRegistration.java new file mode 100644 --- /dev/null +++ b/editor.mimelookup/src/org/netbeans/api/editor/mimelookup/MimeRegistration.java @@ -0,0 +1,77 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2010 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 2010 Sun Microsystems, Inc. + */ +package org.netbeans.api.editor.mimelookup; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +/**Register an implementation of a service to the mime lookup under given mime-type. + * This annotation can be used either to annotate implementation class, in which case + * it must have a public non-arg constructor, or a public static factory method returning + * the service. + * + * @author Jan Lahoda + * @since 1.19 + */ +@Target({ElementType.TYPE, ElementType.METHOD}) +public @interface MimeRegistration { + + /** + * The API service. + */ + public Class service(); + + /** + * Mime type to which should be the given provider registered. + */ + public String mimeType(); + + /** + * Position of the provider in the list of providers. + */ + public int position() default Integer.MAX_VALUE; + + /** + * Superseded providers. + */ + public String[] supersedes() default {}; +} diff --git a/editor.mimelookup/src/org/netbeans/api/editor/mimelookup/MimeRegistrations.java b/editor.mimelookup/src/org/netbeans/api/editor/mimelookup/MimeRegistrations.java new file mode 100644 --- /dev/null +++ b/editor.mimelookup/src/org/netbeans/api/editor/mimelookup/MimeRegistrations.java @@ -0,0 +1,53 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2010 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 2010 Sun Microsystems, Inc. + */ +package org.netbeans.api.editor.mimelookup; + +/**Allows to specify more that one {@link MimeRegistration} for one element. + * + * @author lahvac + * @since 1.19 + */ +public @interface MimeRegistrations { + + public MimeRegistration[] value(); + +} diff --git a/editor.mimelookup/src/org/netbeans/modules/editor/mimelookup/CreateRegistrationProcessor.java b/editor.mimelookup/src/org/netbeans/modules/editor/mimelookup/CreateRegistrationProcessor.java new file mode 100644 --- /dev/null +++ b/editor.mimelookup/src/org/netbeans/modules/editor/mimelookup/CreateRegistrationProcessor.java @@ -0,0 +1,232 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008-2010 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]" + * + * Contributor(s): + * + * Portions Copyrighted 2008-2010 Sun Microsystems, Inc. + */ + +package org.netbeans.modules.editor.mimelookup; + +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; +import javax.annotation.processing.Completion; +import javax.annotation.processing.Processor; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.annotation.processing.SupportedSourceVersion; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.AnnotationValue; +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Name; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; +import org.openide.filesystems.annotations.LayerGeneratingProcessor; +import org.openide.filesystems.annotations.LayerGenerationException; +import org.openide.util.lookup.ServiceProvider; + +/** + * + * @author Jan Lahoda + */ +@SupportedAnnotationTypes({"org.netbeans.api.editor.mimelookup.MimeRegistration", "org.netbeans.api.editor.mimelookup.MimeRegistrations"}) +@SupportedSourceVersion(SourceVersion.RELEASE_6) +@ServiceProvider(service=Processor.class) +public class CreateRegistrationProcessor extends LayerGeneratingProcessor { + + @Override + protected boolean handleProcess(Set annotations, RoundEnvironment roundEnv) throws LayerGenerationException { + TypeElement mimeRegistration = processingEnv.getElementUtils().getTypeElement("org.netbeans.api.editor.mimelookup.MimeRegistration"); + + for (Element el : roundEnv.getElementsAnnotatedWith(mimeRegistration)) { + for (AnnotationMirror am : el.getAnnotationMirrors()) { + if (!mimeRegistration.equals(am.getAnnotationType().asElement())) { + continue; + } + + process(el, am); + } + } + + TypeElement mimeRegistrations = processingEnv.getElementUtils().getTypeElement("org.netbeans.api.editor.mimelookup.MimeRegistrations"); + + for (Element el : roundEnv.getElementsAnnotatedWith(mimeRegistrations)) { + for (AnnotationMirror am : el.getAnnotationMirrors()) { + if (!mimeRegistrations.equals(am.getAnnotationType().asElement())) { + continue; + } + + for (Entry e : am.getElementValues().entrySet()) { + if (!e.getKey().getSimpleName().contentEquals("value")) continue; + + for (AnnotationMirror r : (AnnotationMirror[]) e.getValue().getValue()) { + process(el, r); + } + } + } + } + + return true; + } + + private void process(Element toRegister, AnnotationMirror mimeRegistration) throws LayerGenerationException { + TypeMirror service = null; + String mimeType = null; + int position = Integer.MAX_VALUE; + String[] supersedes = new String[0]; + for (Entry e : mimeRegistration.getElementValues().entrySet()) { + Name simpleName = e.getKey().getSimpleName(); + if (simpleName.contentEquals("service")) { + service = (TypeMirror) e.getValue().getValue(); + continue; + } + if (simpleName.contentEquals("mimeType")) { + mimeType = (String) e.getValue().getValue(); + continue; + } + if (simpleName.contentEquals("position")) { + position = (Integer) e.getValue().getValue(); + continue; + } + if (simpleName.contentEquals("supersedes")) { + position = (Integer) e.getValue().getValue(); + continue; + } + } + + if (mimeType != null) { + if (mimeType.length() != 0) mimeType = "/" + mimeType; + + String folder = ""; + TypeElement apiTE = (TypeElement) processingEnv.getTypeUtils().asElement(service); + TypeElement location = processingEnv.getElementUtils().getTypeElement("org.netbeans.spi.editor.mimelookup.MimeLocation"); + + OUTER: for (AnnotationMirror am : apiTE.getAnnotationMirrors()) { + if (!location.equals(am.getAnnotationType().asElement())) continue; + + for (Entry e : am.getElementValues().entrySet()) { + if (e.getKey().getSimpleName().contentEquals("subfolderName")) { + folder = "/" + (String) e.getValue().getValue(); + break OUTER; + } + } + } + + String fqn = (apiTE).getQualifiedName().toString(); + Class apiClass; + + try { + apiClass = Class.forName(fqn); + } catch (ClassNotFoundException ex) { + //error/warning? + apiClass = null; + } + + layer(toRegister).instanceFile("Editors" + mimeType + folder, null, apiClass).position(position).write(); + + for (String superseded : supersedes) { + layer(toRegister).file("Editors" + mimeType + folder + "/" + superseded + "_hidden").write(); + } + } + } + + @Override + public Iterable getCompletions(Element annotated, AnnotationMirror annotation, ExecutableElement attr, String userText) { + if (processingEnv == null || annotated == null || !annotated.getKind().isClass()) { + return Collections.emptyList(); + } + + if ( annotation == null + || !"org.netbeans.api.editor.mimelookup.MimeRegistration".contentEquals(((TypeElement) annotation.getAnnotationType().asElement()).getQualifiedName())) { + return Collections.emptyList(); + } + + if (!"service".contentEquals(attr.getSimpleName())) { + return Collections.emptyList(); + } + + TypeElement jlObject = processingEnv.getElementUtils().getTypeElement("java.lang.Object"); + + if (jlObject == null) { + return Collections.emptyList(); + } + + Collection result = new LinkedList(); + List toProcess = new LinkedList(); + + toProcess.add((TypeElement) annotated); + + while (!toProcess.isEmpty()) { + TypeElement c = toProcess.remove(0); + + result.add(new TypeCompletion(c.getQualifiedName().toString() + ".class")); + + List parents = new LinkedList(); + + parents.add(c.getSuperclass()); + parents.addAll(c.getInterfaces()); + + for (TypeMirror tm : parents) { + if (tm == null || tm.getKind() != TypeKind.DECLARED) { + continue; + } + + TypeElement type = (TypeElement) processingEnv.getTypeUtils().asElement(tm); + + if (!jlObject.equals(type)) { + toProcess.add(type); + } + } + } + + return result; + } + + private static final class TypeCompletion implements Completion { + + private final String type; + + public TypeCompletion(String type) { + this.type = type; + } + + public String getValue() { + return type; + } + + public String getMessage() { + return null; + } + + } +} diff --git a/editor.mimelookup/src/org/netbeans/spi/editor/mimelookup/MimeLocation.java b/editor.mimelookup/src/org/netbeans/spi/editor/mimelookup/MimeLocation.java new file mode 100644 --- /dev/null +++ b/editor.mimelookup/src/org/netbeans/spi/editor/mimelookup/MimeLocation.java @@ -0,0 +1,69 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2010 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 2010 Sun Microsystems, Inc. + */ + +package org.netbeans.spi.editor.mimelookup; + +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; + +/**Should be used for services that are to be registered to the MimeLookup and that + * need a specific subfolder to be used for the registration (optional, mime-type root + * will be searched if this annotation is missing) + * + * @author Jan Lahoda + * @since 1.19 + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface MimeLocation { + + /** + * Folder under which the services should be registered in the system filesystem. + * The full path for registering the services will then be Editors/<mime-type>/<subfolderName> + */ + public String subfolderName(); + +}