diff -r b3bbc4d76b98 settings/api/doc/org/netbeans/api/settings/package.html
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/settings/api/doc/org/netbeans/api/settings/package.html Tue Dec 23 13:03:05 2008 +0100
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+ org.netbeans.api.settings package
+
+
+ This package provides annotations to simplify use of
+ convertors.
+
+
diff -r b3bbc4d76b98 settings/src/org/netbeans/api/settings/ConvertAsProperties.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/settings/src/org/netbeans/api/settings/ConvertAsProperties.java Tue Dec 23 13:03:05 2008 +0100
@@ -0,0 +1,47 @@
+
+package org.netbeans.api.settings;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.Properties;
+
+/** Annotation to attach to object that is wishing to support conversion from
+ * and to {@link Properties}. More info about the format and protocol
+ * is available in separate document,
+ * here is the shortest possible howto:
+ *
+ * @
ConvertAsProperties(dtd="-//Your Org//Your Setting//EN")
+ * public class YourObject {
+ * public YourObject() {} // public constructor is a must
+ * void readProperties(java.util.Properties p) {
+ * // do the read
+ * }
+ * void writeProperties(java.util.Properties p) {
+ * // handle the store
+ * }
+ * }
+ *
+ *
+ * @author Jaroslav Tulach
+ * @since 1.18
+ */
+@Retention(RetentionPolicy.SOURCE)
+@Target(ElementType.TYPE)
+public @interface ConvertAsProperties {
+ /** Public ID of the XML file that results in creation of the
+ * annotated type and to which the annotated type can be converted.
+ * @return public ID of the file's DTD
+ */
+ String dtd();
+ /** Shall every change in the object result in save? Or shall the
+ * object just be marked as dirty?
+ */
+ boolean autostore() default true;
+ /** An array of properties that are ignored without marking the object
+ * as dirty or saving it.
+ * @return array of property names or "all" to ignore all properties
+ */
+ String[] ignoreChanges() default {};
+}
diff -r b3bbc4d76b98 settings/src/org/netbeans/modules/settings/convertors/ConvertorProcessor.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/settings/src/org/netbeans/modules/settings/convertors/ConvertorProcessor.java Tue Dec 23 13:03:05 2008 +0100
@@ -0,0 +1,262 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
+ * Microsystems, Inc. All Rights Reserved.
+ *
+ * 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.
+ */
+
+package org.netbeans.modules.settings.convertors;
+
+import java.util.Set;
+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.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.ElementFilter;
+import org.netbeans.api.settings.ConvertAsProperties;
+import org.openide.filesystems.annotations.LayerBuilder.File;
+import org.openide.filesystems.annotations.LayerGeneratingProcessor;
+import org.openide.filesystems.annotations.LayerGenerationException;
+import org.openide.util.lookup.ServiceProvider;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/** Processor to hide all the complexities of settings layer registration.
+ *
+ * @author Jaroslav Tulach
+ */
+@ServiceProvider(service=Processor.class)
+@SupportedSourceVersion(SourceVersion.RELEASE_6)
+@SupportedAnnotationTypes("org.netbeans.api.settings.ConvertAsProperties")//NOI18N
+public class ConvertorProcessor extends LayerGeneratingProcessor {
+
+
+ @Override
+ protected boolean handleProcess(
+ Set extends TypeElement> annotations,
+ RoundEnvironment env
+ ) throws LayerGenerationException {
+ for (Element e : env.getElementsAnnotatedWith(ConvertAsProperties.class)) {
+ ConvertAsProperties reg = e.getAnnotation(ConvertAsProperties.class);
+
+ String[] convElem = instantiableClassOrMethod(e, null);
+ final String dtd = reg.dtd();
+
+ String dtdCode = convertPublicId(dtd);
+ System.err.println("dtd: " + dtd);
+ System.err.println("mod: " + dtdCode);
+
+ /*
+
+
+
+
+
+ */
+ layer(e).file("xml/entities" + dtdCode).
+ url("nbres:/org/netbeans/modules/settings/resources/properties-1_0.dtd").
+ stringvalue("hint.originalPublicID", dtd).write();
+ /*
+
+
+
+
+
+
+
+
+ */
+ layer(e).file("xml/memory/" + convElem[0].replace('.', '/')).
+ stringvalue("settings.providerPath", "xml/lookups/" + dtdCode + ".instance").
+ write();
+
+ /*
+
+
+
+
+
+
+
+
+
+ */
+ File f = layer(e).file("xml/lookups" + dtdCode + ".instance").
+ methodvalue("instanceCreate", "org.netbeans.api.settings.Factory", "create").
+ methodvalue("settings.convertor", "org.netbeans.api.settings.Factory", "properties").
+ stringvalue("settings.instanceClass", convElem[0]).
+ stringvalue("settings.instanceOf", convElem[0]).
+ boolvalue("xmlproperties.preventStoring", !reg.autostore());
+ commaSeparated(f, reg.ignoreChanges()).write();
+ }
+ return false;
+ }
+
+ /** Copied from FileEntityResolver from o.n.core module.
+ */
+ @SuppressWarnings("fallthrough")
+ private static String convertPublicId (String publicID) {
+ char[] arr = publicID.toCharArray ();
+
+
+ int numberofslashes = 0;
+ int state = 0;
+ int write = 0;
+ OUT: for (int i = 0; i < arr.length; i++) {
+ char ch = arr[i];
+
+ switch (state) {
+ case 0:
+ // initial state
+ if (ch == '+' || ch == '-' || ch == 'I' || ch == 'S' || ch == 'O') {
+ // do not write that char
+ continue;
+ }
+ // switch to regular state
+ state = 1;
+ // fallthru
+ case 1:
+ // regular state expecting any character
+ if (ch == '/') {
+ state = 2;
+ if (++numberofslashes == 3) {
+ // last part of the ID, exit
+ break OUT;
+ }
+ arr[write++] = '/';
+ continue;
+ }
+ break;
+ case 2:
+ // previous character was /
+ if (ch == '/') {
+ // ignore second / and write nothing
+ continue;
+ }
+ state = 1;
+ break;
+ }
+
+ // write the char into the array
+ if (ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z' || ch >= '0' && ch <= '9') {
+ arr[write++] = ch;
+ } else {
+ arr[write++] = '_';
+ }
+ }
+
+ return new String (arr, 0, write);
+ }
+
+ private static File commaSeparated(File f, String[] arr) {
+ if (arr.length == 0) {
+ return f;
+ }
+
+ StringBuilder sb = new StringBuilder();
+ String sep = "";
+ for (String s : arr) {
+ sb.append(sep);
+ sb.append(s);
+ sep = ",";
+ }
+ return f.stringvalue("xmlproperties.ignoreChanges", sb.toString());
+ }
+
+ private String[] instantiableClassOrMethod(Element e, Class type) throws IllegalArgumentException, LayerGenerationException {
+ TypeMirror typeMirror = type != null ? processingEnv.getElementUtils().getTypeElement(type.getName().replace('$', '.')).asType() : null;
+ switch (e.getKind()) {
+ case CLASS: {
+ String clazz = processingEnv.getElementUtils().getBinaryName((TypeElement) e).toString();
+ if (e.getModifiers().contains(Modifier.ABSTRACT)) {
+ throw new LayerGenerationException(clazz + " must not be abstract", e);
+ }
+ {
+ boolean hasDefaultCtor = false;
+ for (ExecutableElement constructor : ElementFilter.constructorsIn(e.getEnclosedElements())) {
+ if (constructor.getParameters().isEmpty()) {
+ hasDefaultCtor = true;
+ break;
+ }
+ }
+ if (!hasDefaultCtor) {
+ throw new LayerGenerationException(clazz + " must have a no-argument constructor", e);
+ }
+ }
+ if (typeMirror != null && !processingEnv.getTypeUtils().isAssignable(e.asType(), typeMirror)) {
+ throw new LayerGenerationException(clazz + " is not assignable to " + typeMirror, e);
+ }
+ return new String[] {clazz, null};
+ }
+ case METHOD: {
+ String clazz = processingEnv.getElementUtils().getBinaryName((TypeElement) e.getEnclosingElement()).toString();
+ String method = e.getSimpleName().toString();
+ if (!e.getModifiers().contains(Modifier.STATIC)) {
+ throw new LayerGenerationException(clazz + "." + method + " must be static", e);
+ }
+ if (!((ExecutableElement) e).getParameters().isEmpty()) {
+ throw new LayerGenerationException(clazz + "." + method + " must not take arguments", e);
+ }
+ if (typeMirror != null && !processingEnv.getTypeUtils().isAssignable(((ExecutableElement) e).getReturnType(), typeMirror)) {
+ throw new LayerGenerationException(clazz + "." + method + " is not assignable to " + typeMirror, e);
+ }
+ return new String[] {clazz, method};
+ }
+ default:
+ throw new IllegalArgumentException("Annotated element is not loadable as an instance: " + e);
+ }
+ }
+
+ private static final class Parser extends DefaultHandler {
+
+ @Override
+ public void notationDecl(String name, String publicId, String systemId) throws SAXException {
+ super.notationDecl(name, publicId, systemId);
+ System.err.println("pub: " + publicId);
+ System.err.println("sys: " + systemId);
+ System.err.println("name: " + name);
+ }
+
+ }
+}
diff -r b3bbc4d76b98 settings/test/unit/src/org/netbeans/modules/settings/convertors/XMLPropertiesConvertorAnnotationTest.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/settings/test/unit/src/org/netbeans/modules/settings/convertors/XMLPropertiesConvertorAnnotationTest.java Tue Dec 23 13:03:05 2008 +0100
@@ -0,0 +1,93 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Sun Microsystems, Inc. Portions Copyright 2002 Sun
+ * Microsystems, Inc. All Rights Reserved.
+ *
+ * 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.
+ */
+
+package org.netbeans.modules.settings.convertors;
+
+import java.io.*;
+
+import java.util.Properties;
+import org.netbeans.junit.NbTestCase;
+
+
+import org.netbeans.api.settings.ConvertAsProperties;
+import org.netbeans.spi.settings.Convertor;
+
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.Repository;
+
+/** Checks usage of annotation to assign XML properties convertor.
+ *
+ * @author Jaroslav Tulach
+ */
+public final class XMLPropertiesConvertorAnnotationTest extends NbTestCase {
+ /** Creates a new instance of XMLPropertiesConvertorTest */
+ public XMLPropertiesConvertorAnnotationTest(String name) {
+ super(name);
+ }
+
+ public void testReadWrite() throws Exception {
+ FileObject dtdFO = Repository.getDefault().getDefaultFileSystem().
+ findResource("/xml/lookups/NetBeans_org_netbeans_modules_settings_xtest/DTD_XML_FooSetting_2_0.instance");
+ assertNotNull("Provider not found", dtdFO);
+ Convertor c = XMLPropertiesConvertor.create(dtdFO);
+ AnnoFoo foo = new AnnoFoo();
+ foo.setProperty1("xxx");
+ CharArrayWriter caw = new CharArrayWriter(1024);
+ c.write(caw, foo);
+ caw.flush();
+ caw.close();
+ CharArrayReader car = new CharArrayReader(caw.toCharArray());
+ Object obj = c.read(car);
+ assertEquals(foo, obj);
+ }
+
+ @ConvertAsProperties(
+ dtd="-//NetBeans org.netbeans.modules.settings.xtest//DTD XML FooSetting 2.0//EN"
+ )
+ public static class AnnoFoo extends FooSetting {
+ public void readProperties(Properties p) {
+ this.setProperty1(p.getProperty("p1"));
+ }
+ public void writeProperties(Properties p) {
+ p.setProperty("p1", this.getProperty1());
+ }
+ }
+}