diff --git a/ObjectLayout/pom.xml b/ObjectLayout/pom.xml
index 2156d3b..86b0b30 100644
--- a/ObjectLayout/pom.xml
+++ b/ObjectLayout/pom.xml
@@ -25,6 +25,12 @@
4.10
test
+
+ org.netbeans.api
+ org-openide-util-lookup
+ RELEASE80
+ provided
+
@@ -55,8 +61,6 @@
1.7
1.7
-
- -proc:none
UTF-8
diff --git a/ObjectLayout/src/main/java/org/ObjectLayout/IntrinsicProcessor.java b/ObjectLayout/src/main/java/org/ObjectLayout/IntrinsicProcessor.java
index b2ae9ad..00e51b6 100644
--- a/ObjectLayout/src/main/java/org/ObjectLayout/IntrinsicProcessor.java
+++ b/ObjectLayout/src/main/java/org/ObjectLayout/IntrinsicProcessor.java
@@ -5,6 +5,7 @@
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
@@ -16,12 +17,14 @@
import javax.lang.model.element.Modifier;
import javax.tools.Diagnostic;
+import org.openide.util.lookup.ServiceProvider;
/**
* A javac annotation processor for the @Intrinsic annotation.
*/
@SupportedAnnotationTypes("org.ObjectLayout.Intrinsic")
@SupportedSourceVersion(RELEASE_6)
+@ServiceProvider(service = Processor.class)
public class IntrinsicProcessor extends AbstractProcessor {
@Override
public boolean process(Set extends TypeElement> annotations,
diff --git a/ObjectLayout/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/ObjectLayout/src/main/resources/META-INF/services/javax.annotation.processing.Processor
deleted file mode 100644
index 22377b1..0000000
--- a/ObjectLayout/src/main/resources/META-INF/services/javax.annotation.processing.Processor
+++ /dev/null
@@ -1 +0,0 @@
-org.ObjectLayout.IntrinsicProcessor
\ No newline at end of file
diff --git a/ObjectLayout/src/test/java/org/ObjectLayout/Compile.java b/ObjectLayout/src/test/java/org/ObjectLayout/Compile.java
new file mode 100644
index 0000000..0711314
--- /dev/null
+++ b/ObjectLayout/src/test/java/org/ObjectLayout/Compile.java
@@ -0,0 +1,213 @@
+/*
+ * Written by Jaroslav Tulach, and released to the public domain,
+ * as explained at http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+package org.ObjectLayout;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.tools.Diagnostic;
+import javax.tools.DiagnosticListener;
+import javax.tools.FileObject;
+import javax.tools.ForwardingJavaFileManager;
+import javax.tools.JavaFileManager;
+import javax.tools.JavaFileObject;
+import javax.tools.JavaFileObject.Kind;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+import static org.junit.Assert.fail;
+
+final class Compile implements DiagnosticListener {
+ private final List> errors = new ArrayList<>();
+ private final Map classes;
+ private final String pkg;
+ private final String cls;
+
+ private Compile(String code) throws IOException {
+ this.pkg = findPkg(code);
+ this.cls = findCls(code);
+ classes = compile(code);
+ }
+
+ /** Performs compilation of given Java code
+ */
+ public static Compile create(String code) throws IOException {
+ return new Compile(code);
+ }
+
+ /** Checks for given class among compiled resources */
+ public byte[] get(String res) {
+ return classes.get(res);
+ }
+
+ /** Obtains errors created during compilation.
+ */
+ public List> getErrors() {
+ List> err = new ArrayList<>();
+ for (Diagnostic extends JavaFileObject> diagnostic : errors) {
+ if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
+ err.add(diagnostic);
+ }
+ }
+ return err;
+ }
+
+ private Map compile(final String code) throws IOException {
+ StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(this, null, null);
+
+ final Map class2BAOS = new HashMap<>();
+
+ JavaFileObject file = new Mem(URI.create("mem://mem"), Kind.SOURCE, code);
+
+ final URI scratch;
+ try {
+ scratch = new URI("mem://mem3");
+ } catch (URISyntaxException ex) {
+ throw new IOException(ex);
+ }
+
+ JavaFileManager jfm = new ForwardingJavaFileManagerImpl(sjfm, class2BAOS, scratch);
+
+ ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, /*XXX:*/Arrays.asList("-source", "1.7", "-target", "1.7"), null, Arrays.asList(file)).call();
+
+ Map result = new HashMap<>();
+
+ for (Map.Entry e : class2BAOS.entrySet()) {
+ result.put(e.getKey(), e.getValue().toByteArray());
+ }
+
+ return result;
+ }
+
+
+ @Override
+ public void report(Diagnostic extends JavaFileObject> diagnostic) {
+ errors.add(diagnostic);
+ }
+ private static String findPkg(String java) throws IOException {
+ Pattern p = Pattern.compile("package\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}*;", Pattern.MULTILINE);
+ Matcher m = p.matcher(java);
+ if (!m.find()) {
+ throw new IOException("Can't find package declaration in the java file");
+ }
+ String pkg = m.group(1);
+ return pkg;
+ }
+ private static String findCls(String java) throws IOException {
+ Pattern p = Pattern.compile("class\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}", Pattern.MULTILINE);
+ Matcher m = p.matcher(java);
+ if (!m.find()) {
+ throw new IOException("Can't find package declaration in the java file");
+ }
+ String cls = m.group(1);
+ return cls;
+ }
+
+ void assertError(String msg) {
+ if (getErrors().isEmpty()) {
+ fail(msg + " there should be no errors");
+ }
+ StringBuilder sb = new StringBuilder();
+ for (Diagnostic extends JavaFileObject> err : errors) {
+ final String txt = err.getMessage(Locale.US);
+ if (txt.contains(msg)) {
+ return;
+ }
+ sb.append("\n").append(txt);
+ }
+ fail(msg + sb);
+ }
+
+ private class ForwardingJavaFileManagerImpl extends ForwardingJavaFileManager {
+
+ private final Map class2BAOS;
+ private final URI scratch;
+
+ public ForwardingJavaFileManagerImpl(JavaFileManager fileManager, Map class2BAOS, URI scratch) {
+ super(fileManager);
+ this.class2BAOS = class2BAOS;
+ this.scratch = scratch;
+ }
+
+ @Override
+ public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
+ if (kind == Kind.CLASS) {
+ final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+
+ class2BAOS.put(className.replace('.', '/') + ".class", buffer);
+ return new Sibling(sibling.toUri(), kind, buffer);
+ }
+
+ if (kind == Kind.SOURCE) {
+ return new Source(scratch/*sibling.toUri()*/, kind);
+ }
+
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
+ return null;
+ }
+
+ private class Sibling extends SimpleJavaFileObject {
+ private final ByteArrayOutputStream buffer;
+
+ public Sibling(URI uri, Kind kind, ByteArrayOutputStream buffer) {
+ super(uri, kind);
+ this.buffer = buffer;
+ }
+
+ @Override
+ public OutputStream openOutputStream() throws IOException {
+ return buffer;
+ }
+ }
+
+ private class Source extends SimpleJavaFileObject {
+ public Source(URI uri, Kind kind) {
+ super(uri, kind);
+ }
+ private final ByteArrayOutputStream data = new ByteArrayOutputStream();
+
+ @Override
+ public OutputStream openOutputStream() throws IOException {
+ return data;
+ }
+
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
+ data.close();
+ return new String(data.toByteArray());
+ }
+ }
+ }
+
+ private static class Mem extends SimpleJavaFileObject {
+
+ private final String code;
+
+ public Mem(URI uri, Kind kind, String code) {
+ super(uri, kind);
+ this.code = code;
+ }
+
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
+ return code;
+ }
+ }
+}
diff --git a/ObjectLayout/src/test/java/org/ObjectLayout/IntrinsicProcessorTest.java b/ObjectLayout/src/test/java/org/ObjectLayout/IntrinsicProcessorTest.java
new file mode 100644
index 0000000..0736560
--- /dev/null
+++ b/ObjectLayout/src/test/java/org/ObjectLayout/IntrinsicProcessorTest.java
@@ -0,0 +1,48 @@
+/*
+ * Written by Jaroslav Tulach, and released to the public domain,
+ * as explained at http://creativecommons.org/publicdomain/zero/1.0/
+ */
+package org.ObjectLayout;
+
+import org.junit.Test;
+
+public class IntrinsicProcessorTest {
+
+ @Test public void nonPrivateIntrinsicObjectMember() throws Exception {
+ Compile c = Compile.create(
+"package org.ObjectLayoutTest;\n" +
+"import org.ObjectLayout.*;\n" +
+"class BadContainerNonPrivate {\n" +
+" @Intrinsic\n" +
+" final Point intrinsicPoint = IntrinsicObjects.constructWithin(\"intrinsicPoint\", this);\n" +
+"\n" +
+" Point getPoint() {\n" +
+" return intrinsicPoint;\n" +
+" }\n" +
+"}\n" +
+"class Point {\n" +
+"}\n"
+ );
+ c.assertError("@Intrinsic object annotations can only be declared for private final fields");
+ }
+
+ @Test public void nonFinalIntrinsicObjectMember() throws Exception {
+ Compile c = Compile.create(
+"package org.ObjectLayoutTest;\n" +
+"import org.ObjectLayout.*;\n" +
+"class BadContainerNonFinal {\n" +
+" @Intrinsic\n" +
+" private Point intrinsicPoint = IntrinsicObjects.constructWithin(\"intrinsicPoint\", this);\n" +
+"\n" +
+" Point getPoint() {\n" +
+" return intrinsicPoint;\n" +
+" }\n" +
+"}\n" +
+"class Point {\n" +
+"}\n"
+ );
+ c.assertError("@Intrinsic object annotations can only be declared for private final fields");
+ }
+
+
+}
diff --git a/ObjectLayout/src/test/java/org/ObjectLayout/IntrinsticObjectTest.java b/ObjectLayout/src/test/java/org/ObjectLayout/IntrinsticObjectTest.java
index e810f72..c8953b8 100644
--- a/ObjectLayout/src/test/java/org/ObjectLayout/IntrinsticObjectTest.java
+++ b/ObjectLayout/src/test/java/org/ObjectLayout/IntrinsticObjectTest.java
@@ -119,42 +119,6 @@ public void testBadContainerNonIntrinsic() throws NoSuchMethodException {
bad.getPoint().getX();
}
- /**
- * BadContainerNonPrivate: non private intrinsic object member
- */
- static class BadContainerNonPrivate {
- @Intrinsic
- final Point intrinsicPoint = IntrinsicObjects.constructWithin("intrinsicPoint", this);
-
- Point getPoint() {
- return intrinsicPoint;
- }
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testBadContainerNonPrivate() throws NoSuchMethodException {
- BadContainerNonPrivate bad = new BadContainerNonPrivate();
- bad.getPoint().getX();
- }
-
- /**
- * BadContainerNonFinal: non final intrinsic object member
- */
- static class BadContainerNonFinal {
- @Intrinsic
- private Point intrinsicPoint = IntrinsicObjects.constructWithin("intrinsicPoint", this);
-
- Point getPoint() {
- return intrinsicPoint;
- }
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testBadContainerNonFinal() throws NoSuchMethodException {
- BadContainerNonFinal bad = new BadContainerNonFinal();
- bad.getPoint().getX();
- }
-
/**
* BadContainerNullMember: null intrinsic object member
*/
diff --git a/pom.xml b/pom.xml
index e03d5ff..48dcbb7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -14,6 +14,14 @@
UTF-8
+
+
+
+ netbeans
+ netbeans
+ http://bits.netbeans.org/maven2/
+
+
ObjectLayout