1.1 --- a/openide.util.lookup/src/org/netbeans/modules/openide/util/AbstractServiceProviderProcessor.java Fri Jan 22 14:50:19 2010 +0100
1.2 +++ b/openide.util.lookup/src/org/netbeans/modules/openide/util/AbstractServiceProviderProcessor.java Fri Jan 22 10:09:12 2010 -0500
1.3 @@ -72,8 +72,6 @@
1.4 /**
1.5 * Infrastructure for generating {@code META-INF/services/*} and
1.6 * {@code META-INF/namedservices/*} registrations from annotations.
1.7 - *
1.8 - * NOTE: This class is duplicated in openide.util and openide.util.lookup to prevent implementation dependency.
1.9 */
1.10 public abstract class AbstractServiceProviderProcessor extends AbstractProcessor {
1.11
2.1 --- a/openide.util.lookup/src/org/netbeans/modules/openide/util/ActiveQueue.java Fri Jan 22 14:50:19 2010 +0100
2.2 +++ b/openide.util.lookup/src/org/netbeans/modules/openide/util/ActiveQueue.java Fri Jan 22 10:09:12 2010 -0500
2.3 @@ -7,8 +7,6 @@
2.4
2.5 /**
2.6 * Implementation of the active reference queue.
2.7 - *
2.8 - * NOTE: This class is duplicated in openide.util and openide.util.lookup to prevent implementation dependency.
2.9 */
2.10 public final class ActiveQueue extends ReferenceQueue<Object> implements Runnable {
2.11
3.1 --- a/openide.util/nbproject/project.xml Fri Jan 22 14:50:19 2010 +0100
3.2 +++ b/openide.util/nbproject/project.xml Fri Jan 22 10:09:12 2010 -0500
3.3 @@ -51,7 +51,7 @@
3.4 <build-prerequisite/>
3.5 <compile-dependency/>
3.6 <run-dependency>
3.7 - <specification-version>8.0</specification-version>
3.8 + <implementation-version/>
3.9 </run-dependency>
3.10 </dependency>
3.11 </module-dependencies>
4.1 --- a/openide.util/src/org/netbeans/modules/openide/util/AbstractServiceProviderProcessor.java Fri Jan 22 14:50:19 2010 +0100
4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
4.3 @@ -1,298 +0,0 @@
4.4 -/*
4.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4.6 - *
4.7 - * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
4.8 - *
4.9 - * The contents of this file are subject to the terms of either the GNU
4.10 - * General Public License Version 2 only ("GPL") or the Common
4.11 - * Development and Distribution License("CDDL") (collectively, the
4.12 - * "License"). You may not use this file except in compliance with the
4.13 - * License. You can obtain a copy of the License at
4.14 - * http://www.netbeans.org/cddl-gplv2.html
4.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
4.16 - * specific language governing permissions and limitations under the
4.17 - * License. When distributing the software, include this License Header
4.18 - * Notice in each file and include the License file at
4.19 - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
4.20 - * particular file as subject to the "Classpath" exception as provided
4.21 - * by Sun in the GPL Version 2 section of the License file that
4.22 - * accompanied this code. If applicable, add the following below the
4.23 - * License Header, with the fields enclosed by brackets [] replaced by
4.24 - * your own identifying information:
4.25 - * "Portions Copyrighted [year] [name of copyright owner]"
4.26 - *
4.27 - * If you wish your version of this file to be governed by only the CDDL
4.28 - * or only the GPL Version 2, indicate your decision by adding
4.29 - * "[Contributor] elects to include this software in this distribution
4.30 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
4.31 - * single choice of license, a recipient has the option to distribute
4.32 - * your version of this file under either the CDDL, the GPL Version 2 or
4.33 - * to extend the choice of license to its licensees as provided above.
4.34 - * However, if you add GPL Version 2 code and therefore, elected the GPL
4.35 - * Version 2 license, then the option applies only if the new code is
4.36 - * made subject to such option by the copyright holder.
4.37 - *
4.38 - * Contributor(s):
4.39 - *
4.40 - * Portions Copyrighted 2009 Sun Microsystems, Inc.
4.41 - */
4.42 -
4.43 -package org.netbeans.modules.openide.util;
4.44 -
4.45 -import java.io.BufferedReader;
4.46 -import java.io.FileNotFoundException;
4.47 -import java.io.IOException;
4.48 -import java.io.InputStream;
4.49 -import java.io.InputStreamReader;
4.50 -import java.io.OutputStream;
4.51 -import java.io.OutputStreamWriter;
4.52 -import java.io.PrintWriter;
4.53 -import java.lang.annotation.Annotation;
4.54 -import java.util.ArrayList;
4.55 -import java.util.HashMap;
4.56 -import java.util.List;
4.57 -import java.util.Map;
4.58 -import java.util.Set;
4.59 -import java.util.WeakHashMap;
4.60 -import javax.annotation.processing.AbstractProcessor;
4.61 -import javax.annotation.processing.ProcessingEnvironment;
4.62 -import javax.annotation.processing.RoundEnvironment;
4.63 -import javax.lang.model.element.AnnotationMirror;
4.64 -import javax.lang.model.element.AnnotationValue;
4.65 -import javax.lang.model.element.Element;
4.66 -import javax.lang.model.element.ExecutableElement;
4.67 -import javax.lang.model.element.Modifier;
4.68 -import javax.lang.model.element.TypeElement;
4.69 -import javax.lang.model.type.TypeMirror;
4.70 -import javax.lang.model.util.ElementFilter;
4.71 -import javax.tools.Diagnostic.Kind;
4.72 -import javax.tools.FileObject;
4.73 -import javax.tools.StandardLocation;
4.74 -
4.75 -/**
4.76 - * Infrastructure for generating {@code META-INF/services/*} and
4.77 - * {@code META-INF/namedservices/*} registrations from annotations.
4.78 - *
4.79 - * NOTE: This class is duplicated in openide.util and openide.util.lookup to prevent implementation dependency.
4.80 - */
4.81 -public abstract class AbstractServiceProviderProcessor extends AbstractProcessor {
4.82 -
4.83 - private final Map<ProcessingEnvironment,Map<String,List<String>>> outputFilesByProcessor = new WeakHashMap<ProcessingEnvironment,Map<String,List<String>>>();
4.84 - private final Map<ProcessingEnvironment,Map<String,List<Element>>> originatingElementsByProcessor = new WeakHashMap<ProcessingEnvironment,Map<String,List<Element>>>();
4.85 - private final Map<TypeElement,Boolean> verifiedClasses = new WeakHashMap<TypeElement,Boolean>();
4.86 -
4.87 - /** For access by subclasses. */
4.88 - protected AbstractServiceProviderProcessor() {}
4.89 -
4.90 - public @Override final boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
4.91 - if (roundEnv.errorRaised()) {
4.92 - return false;
4.93 - }
4.94 - if (roundEnv.processingOver()) {
4.95 - writeServices();
4.96 - outputFilesByProcessor.clear();
4.97 - originatingElementsByProcessor.clear();
4.98 - return true;
4.99 - } else {
4.100 - return handleProcess(annotations, roundEnv);
4.101 - }
4.102 - }
4.103 -
4.104 - /**
4.105 - * The regular body of {@link #process}.
4.106 - * Called during regular rounds if there are no outstanding errors.
4.107 - * In the last round, one of the processors will write out generated registrations.
4.108 - * @param annotations as in {@link #process}
4.109 - * @param roundEnv as in {@link #process}
4.110 - * @return as in {@link #process}
4.111 - */
4.112 - protected abstract boolean handleProcess(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv);
4.113 -
4.114 - /**
4.115 - * Register a service.
4.116 - * If the class does not have an appropriate signature, an error will be printed and the registration skipped.
4.117 - * @param clazz the service implementation type
4.118 - * @param annotation the (top-level) annotation registering the service, for diagnostic purposes
4.119 - * @param type the type to which the implementation must be assignable
4.120 - * @param path a path under which to register, or "" if inapplicable
4.121 - * @param position a position at which to register, or {@link Integer#MAX_VALUE} to skip
4.122 - * @param supersedes possibly empty list of implementation to supersede
4.123 - */
4.124 - protected final void register(TypeElement clazz, Class<? extends Annotation> annotation,
4.125 - TypeMirror type, String path, int position, String[] supersedes) {
4.126 - Boolean verify = verifiedClasses.get(clazz);
4.127 - if (verify == null) {
4.128 - verify = verifyServiceProviderSignature(clazz, annotation);
4.129 - verifiedClasses.put(clazz, verify);
4.130 - }
4.131 - if (!verify) {
4.132 - return;
4.133 - }
4.134 - String impl = processingEnv.getElementUtils().getBinaryName(clazz).toString();
4.135 - String xface = processingEnv.getElementUtils().getBinaryName((TypeElement) processingEnv.getTypeUtils().asElement(type)).toString();
4.136 - if (!processingEnv.getTypeUtils().isAssignable(clazz.asType(), type)) {
4.137 - AnnotationMirror ann = findAnnotationMirror(clazz, annotation);
4.138 - processingEnv.getMessager().printMessage(Kind.ERROR, impl + " is not assignable to " + xface,
4.139 - clazz, ann, findAnnotationValue(ann, "service"));
4.140 - return;
4.141 - }
4.142 - processingEnv.getMessager().printMessage(Kind.NOTE,
4.143 - impl + " to be registered as a " + xface + (path.length() > 0 ? " under " + path : ""));
4.144 - String rsrc = (path.length() > 0 ? "META-INF/namedservices/" + path + "/" : "META-INF/services/") + xface;
4.145 - {
4.146 - Map<String,List<Element>> originatingElements = originatingElementsByProcessor.get(processingEnv);
4.147 - if (originatingElements == null) {
4.148 - originatingElements = new HashMap<String,List<Element>>();
4.149 - originatingElementsByProcessor.put(processingEnv, originatingElements);
4.150 - }
4.151 - List<Element> origEls = originatingElements.get(rsrc);
4.152 - if (origEls == null) {
4.153 - origEls = new ArrayList<Element>();
4.154 - originatingElements.put(rsrc, origEls);
4.155 - }
4.156 - origEls.add(clazz);
4.157 - }
4.158 - Map<String,List<String>> outputFiles = outputFilesByProcessor.get(processingEnv);
4.159 - if (outputFiles == null) {
4.160 - outputFiles = new HashMap<String,List<String>>();
4.161 - outputFilesByProcessor.put(processingEnv, outputFiles);
4.162 - }
4.163 - List<String> lines = outputFiles.get(rsrc);
4.164 - if (lines == null) {
4.165 - lines = new ArrayList<String>();
4.166 - try {
4.167 - try {
4.168 - FileObject in = processingEnv.getFiler().getResource(StandardLocation.SOURCE_PATH, "", rsrc);
4.169 - in.openInputStream().close();
4.170 - processingEnv.getMessager().printMessage(Kind.ERROR,
4.171 - "Cannot generate " + rsrc + " because it already exists in sources: " + in.toUri());
4.172 - return;
4.173 - } catch (NullPointerException ex) {
4.174 - // trying to prevent java.lang.NullPointerException
4.175 - // at com.sun.tools.javac.util.DefaultFileManager.getFileForOutput(DefaultFileManager.java:1078)
4.176 - // at com.sun.tools.javac.util.DefaultFileManager.getFileForOutput(DefaultFileManager.java:1054)
4.177 - // at com.sun.tools.javac.processing.JavacFiler.getResource(JavacFiler.java:434)
4.178 - // at org.netbeans.modules.openide.util.AbstractServiceProviderProcessor.register(AbstractServiceProviderProcessor.java:163)
4.179 - // at org.netbeans.modules.openide.util.ServiceProviderProcessor.register(ServiceProviderProcessor.java:99)
4.180 - } catch (FileNotFoundException x) {
4.181 - // Good.
4.182 - }
4.183 - try {
4.184 - FileObject in = processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", rsrc);
4.185 - InputStream is = in.openInputStream();
4.186 - try {
4.187 - BufferedReader r = new BufferedReader(new InputStreamReader(is, "UTF-8"));
4.188 - String line;
4.189 - while ((line = r.readLine()) != null) {
4.190 - lines.add(line);
4.191 - }
4.192 - } finally {
4.193 - is.close();
4.194 - }
4.195 - } catch (FileNotFoundException x) {
4.196 - // OK, created for the first time
4.197 - }
4.198 - } catch (IOException x) {
4.199 - processingEnv.getMessager().printMessage(Kind.ERROR, x.toString());
4.200 - return;
4.201 - }
4.202 - outputFiles.put(rsrc, lines);
4.203 - }
4.204 - int idx = lines.indexOf(impl);
4.205 - if (idx != -1) {
4.206 - lines.remove(idx);
4.207 - while (lines.size() > idx && lines.get(idx).matches("#position=.+|#-.+")) {
4.208 - lines.remove(idx);
4.209 - }
4.210 - }
4.211 - lines.add(impl);
4.212 - if (position != Integer.MAX_VALUE) {
4.213 - lines.add("#position=" + position);
4.214 - }
4.215 - for (String exclude : supersedes) {
4.216 - lines.add("#-" + exclude);
4.217 - }
4.218 - }
4.219 -
4.220 - /**
4.221 - * @param element a source element
4.222 - * @param annotation a type of annotation
4.223 - * @return the instance of that annotation on the element, or null if not found
4.224 - */
4.225 - private AnnotationMirror findAnnotationMirror(Element element, Class<? extends Annotation> annotation) {
4.226 - for (AnnotationMirror ann : element.getAnnotationMirrors()) {
4.227 - if (processingEnv.getElementUtils().getBinaryName((TypeElement) ann.getAnnotationType().asElement()).
4.228 - contentEquals(annotation.getName())) {
4.229 - return ann;
4.230 - }
4.231 - }
4.232 - return null;
4.233 - }
4.234 -
4.235 - /**
4.236 - * @param annotation an annotation instance (null permitted)
4.237 - * @param name the name of an attribute of that annotation
4.238 - * @return the corresponding value if found
4.239 - */
4.240 - private AnnotationValue findAnnotationValue(AnnotationMirror annotation, String name) {
4.241 - if (annotation != null) {
4.242 - for (Map.Entry<? extends ExecutableElement,? extends AnnotationValue> entry : annotation.getElementValues().entrySet()) {
4.243 - if (entry.getKey().getSimpleName().contentEquals(name)) {
4.244 - return entry.getValue();
4.245 - }
4.246 - }
4.247 - }
4.248 - return null;
4.249 - }
4.250 -
4.251 - private final boolean verifyServiceProviderSignature(TypeElement clazz, Class<? extends Annotation> annotation) {
4.252 - AnnotationMirror ann = findAnnotationMirror(clazz, annotation);
4.253 - if (!clazz.getModifiers().contains(Modifier.PUBLIC)) {
4.254 - processingEnv.getMessager().printMessage(Kind.ERROR, clazz + " must be public", clazz, ann);
4.255 - return false;
4.256 - }
4.257 - if (clazz.getModifiers().contains(Modifier.ABSTRACT)) {
4.258 - processingEnv.getMessager().printMessage(Kind.ERROR, clazz + " must not be abstract", clazz, ann);
4.259 - return false;
4.260 - }
4.261 - {
4.262 - boolean hasDefaultCtor = false;
4.263 - for (ExecutableElement constructor : ElementFilter.constructorsIn(clazz.getEnclosedElements())) {
4.264 - if (constructor.getModifiers().contains(Modifier.PUBLIC) && constructor.getParameters().isEmpty()) {
4.265 - hasDefaultCtor = true;
4.266 - break;
4.267 - }
4.268 - }
4.269 - if (!hasDefaultCtor) {
4.270 - processingEnv.getMessager().printMessage(Kind.ERROR, clazz + " must have a public no-argument constructor", clazz, ann);
4.271 - return false;
4.272 - }
4.273 - }
4.274 - return true;
4.275 - }
4.276 -
4.277 - private void writeServices() {
4.278 - for (Map.Entry<ProcessingEnvironment,Map<String,List<String>>> outputFiles : outputFilesByProcessor.entrySet()) {
4.279 - for (Map.Entry<String, List<String>> entry : outputFiles.getValue().entrySet()) {
4.280 - try {
4.281 - FileObject out = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", entry.getKey(),
4.282 - originatingElementsByProcessor.get(outputFiles.getKey()).get(entry.getKey()).toArray(new Element[0]));
4.283 - OutputStream os = out.openOutputStream();
4.284 - try {
4.285 - PrintWriter w = new PrintWriter(new OutputStreamWriter(os, "UTF-8"));
4.286 - for (String line : entry.getValue()) {
4.287 - w.println(line);
4.288 - }
4.289 - w.flush();
4.290 - w.close();
4.291 - } finally {
4.292 - os.close();
4.293 - }
4.294 - } catch (IOException x) {
4.295 - processingEnv.getMessager().printMessage(Kind.ERROR, "Failed to write to " + entry.getKey() + ": " + x.toString());
4.296 - }
4.297 - }
4.298 - }
4.299 - }
4.300 -
4.301 -}
5.1 --- a/openide.util/src/org/netbeans/modules/openide/util/ActiveQueue.java Fri Jan 22 14:50:19 2010 +0100
5.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
5.3 @@ -1,110 +0,0 @@
5.4 -package org.netbeans.modules.openide.util;
5.5 -
5.6 -import java.lang.ref.Reference;
5.7 -import java.lang.ref.ReferenceQueue;
5.8 -import java.util.logging.Level;
5.9 -import java.util.logging.Logger;
5.10 -
5.11 -/**
5.12 - * Implementation of the active reference queue.
5.13 - *
5.14 - * NOTE: This class is duplicated in openide.util and openide.util.lookup to prevent implementation dependency.
5.15 - */
5.16 -public final class ActiveQueue extends ReferenceQueue<Object> implements Runnable {
5.17 -
5.18 - private static final Logger LOGGER = Logger.getLogger(ActiveQueue.class.getName().replace('$', '.'));
5.19 - private static ActiveQueue activeReferenceQueue;
5.20 -
5.21 - /** number of known outstanding references */
5.22 - private int count;
5.23 - private boolean deprecated;
5.24 -
5.25 - ActiveQueue(boolean deprecated) {
5.26 - super();
5.27 - this.deprecated = deprecated;
5.28 - }
5.29 -
5.30 - public static synchronized ReferenceQueue<Object> queue() {
5.31 - if (activeReferenceQueue == null) {
5.32 - activeReferenceQueue = new ActiveQueue(false);
5.33 - }
5.34 -
5.35 - activeReferenceQueue.ping();
5.36 -
5.37 - return activeReferenceQueue;
5.38 - }
5.39 -
5.40 - @Override
5.41 - public Reference<Object> poll() {
5.42 - throw new UnsupportedOperationException();
5.43 - }
5.44 -
5.45 - @Override
5.46 - public Reference<Object> remove(long timeout) throws IllegalArgumentException, InterruptedException {
5.47 - throw new InterruptedException();
5.48 - }
5.49 -
5.50 - @Override
5.51 - public Reference<Object> remove() throws InterruptedException {
5.52 - throw new InterruptedException();
5.53 - }
5.54 -
5.55 - public void run() {
5.56 - while (true) {
5.57 - try {
5.58 - Reference<?> ref = super.remove(0);
5.59 - LOGGER.finer("dequeued reference");
5.60 - if (!(ref instanceof Runnable)) {
5.61 - LOGGER.warning("A reference not implementing runnable has been added to the Utilities.activeReferenceQueue(): " + ref.getClass());
5.62 - continue;
5.63 - }
5.64 - if (deprecated) {
5.65 - LOGGER.warning("Utilities.ACTIVE_REFERENCE_QUEUE has been deprecated for " + ref.getClass() + " use Utilities.activeReferenceQueue");
5.66 - }
5.67 - // do the cleanup
5.68 - try {
5.69 - ((Runnable) ref).run();
5.70 - } catch (ThreadDeath td) {
5.71 - throw td;
5.72 - } catch (Throwable t) {
5.73 - // Should not happen.
5.74 - // If it happens, it is a bug in client code, notify!
5.75 - LOGGER.log(Level.WARNING, null, t);
5.76 - } finally {
5.77 - // to allow GC
5.78 - ref = null;
5.79 - }
5.80 - } catch (InterruptedException ex) {
5.81 - // Can happen during VM shutdown, it seems. Ignore.
5.82 - continue;
5.83 - }
5.84 - synchronized (this) {
5.85 - assert count > 0;
5.86 - count--;
5.87 - if (count == 0) {
5.88 - // We have processed all we have to process (for now at least).
5.89 - // Could be restarted later if ping() called again.
5.90 - // This could also happen in case someone called queue() once and tried
5.91 - // to use it for several references; in that case run() might never be called on
5.92 - // the later ones to be collected. Can't really protect against that situation.
5.93 - // See issue #86625 for details.
5.94 - LOGGER.fine("stopping thread");
5.95 - break;
5.96 - }
5.97 - }
5.98 - }
5.99 - }
5.100 -
5.101 - synchronized void ping() {
5.102 - if (count == 0) {
5.103 - Thread t = new Thread(this, "Active Reference Queue Daemon");
5.104 - t.setPriority(Thread.MIN_PRIORITY);
5.105 - t.setDaemon(true);
5.106 - t.start();
5.107 - LOGGER.fine("starting thread");
5.108 - } else {
5.109 - LOGGER.finer("enqueuing reference");
5.110 - }
5.111 - count++;
5.112 - }
5.113 -}