All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.html.context.spi.Contexts Maven / Gradle / Ivy

The newest version!
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.netbeans.html.context.spi;

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 java.util.ServiceLoader;
import net.java.html.BrwsrCtx;
import org.netbeans.html.context.impl.CtxImpl;

/** Factory class to assign various technologies 
 * to a {@link BrwsrCtx browser context}. Start with {@link #newBuilder()}
 * and then assign technologies with {@link Builder#register(java.lang.Class, java.lang.Object, int)}
 * method.
 *
 * @author Jaroslav Tulach
 */
public final class Contexts {
    private Contexts() {
    }

    /** Creates new, empty builder for creation of {@link BrwsrCtx}. At the
     * end call the {@link Builder#build()} method to generate the context.
     * 
     * @param context instances of various classes or names of {@link Id technologies} 
     *    to be preferred and used in the built {@link BrwsrCtx context}.
     * @return new instance of the builder
     * @since 1.1
     */
    public static Builder newBuilder(Object... context) {
        return new Builder(context);
    }
    /** Creates new, empty builder for creation of {@link BrwsrCtx}. At the
     * end call the {@link Builder#build()} method to generate the context.
     * Simply calls {@link #newBuilder(java.lang.Object...) newBuilder(new Object[0])}.
     * 
     * @return new instance of the builder
     */
    public static Builder newBuilder() {
        return newBuilder(new Object[0]);
    }

    /** Seeks for the specified technology in the provided context.
     * 
     * @param  type of the technology
     * @param context the context to seek in 
     *    (previously filled with ({@link Builder#register(java.lang.Class, java.lang.Object, int)})
     * @param technology class that identifies the technology
     * @return the technology in the context or null
     */
    public static  Tech find(BrwsrCtx context, Class technology) {
        return CtxImpl.find(context, technology);
    }

    /** Seeks {@link ServiceLoader} for all registered instances of
     * {@link Provider} and asks them to {@link Provider#fillContext(org.netbeans.html.context.spi.Contexts.Builder, java.lang.Class) fill
     * the builder}.
     * 
     * @param requestor the application class for which to find the context
     * @param cb the context builder to register technologies into
     * @return true, if some instances of the provider were
     *    found, false otherwise
     * @since 0.7.6
     */
    public static boolean fillInByProviders(Class requestor, Contexts.Builder cb) {
        boolean found = false;
        ClassLoader l;
        try {
            l = requestor.getClassLoader();
        } catch (SecurityException ex) {
            l = null;
        }
        ClassSet classes = new ClassSet(null);
        for (Provider cp : ServiceLoader.load(Provider.class, l)) {
            if (!classes.add(cp.getClass())) {
                continue;
            }
            cp.fillContext(cb, requestor);
            found = true;
        }
        try {
            for (Provider cp : ServiceLoader.load(Provider.class, Provider.class.getClassLoader())) {
                if (!classes.add(cp.getClass())) {
                    continue;
                }
                cp.fillContext(cb, requestor);
                found = true;
            }
        } catch (SecurityException ex) {
            if (!found) {
                throw ex;
            }
        }
        if (!found) {
            for (Provider cp : ServiceLoader.load(Provider.class)) {
                if (!classes.add(cp.getClass())) {
                    continue;
                }
                cp.fillContext(cb, requestor);
                found = true;
            }
        }
        return found;
    }

    private static class ClassSet {
        private final Class clazz;
        private ClassSet next;

        public ClassSet(Class clazz) {
            this.clazz = clazz;
        }


        boolean add(Class c) {
            if (clazz == c) {
                return false;
            }
            if (next == null) {
                next = new ClassSet(c);
                return true;
            } else {
                return next.add(c);
            }
        }
    }
    
    /** Identifies the technologies passed to {@link Builder context builder}
     * by a name. Each implementation of a technology 
     * {@link Builder#register(java.lang.Class, java.lang.Object, int) registered into a context}
     * can be annotated with a name (or multiple names). Such implementation
     * will later be 
     * {@link Contexts#fillInByProviders(java.lang.Class, org.netbeans.html.context.spi.Contexts.Builder)  preferred during lookup}
     * if their name(s) has been requested in when 
     * {@link Contexts#newBuilder(java.lang.Object...)  creating a context}.
     * @since 1.1
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @Documented
    public @interface Id {
        /** Identifier(s) for the implementation. 
         * 
         * @return one of more identifiers giving this implementation name(s)
         */
        public String[] value();
    }

    /** Implementors of various HTML technologies should
     * register their implementation via org.openide.util.lookup.ServiceProvider, so
     * {@link ServiceLoader} can find them, when their JARs are included
     * on the classpath of the running application.
     *
     * @author Jaroslav Tulach
     */
    public static interface Provider {

        /** Register into the context if suitable technology is
         * available for the requesting class.
         * The provider should check if its own technology is available in current
         * scope (e.g. proper JDK, proper browser, etc.). The provider
         * can also find the right context depending on requestor's classloader, etc.
         * 

* Providers should use {@link Builder} to enrich appropriately * the context. * * @param context the context builder to fill with technologies * @param requestor the application class requesting access the the HTML page * @see BrwsrCtx#findDefault(java.lang.Class) */ void fillContext(Builder context, Class requestor); } /** Support for providers of new {@link BrwsrCtx}. Providers of different * technologies should be of particular interest in this class. End users * designing their application with existing technologies should rather * point their attention to {@link BrwsrCtx} and co. * * @author Jaroslav Tulach */ public static final class Builder { private final CtxImpl impl; public Builder(Object[] context) { this.impl = new CtxImpl(context); } /** Registers new technology into the context. Each technology is * exactly identified by its implementation class and can be associated * with (positive) priority. In case of presence of multiple technologies * with the same class, the one with higher lower priority takes precedence. * @param type of technology to register * @param type the real class of the technology type * @param impl an instance of the technology class * @param position the lower position (but higher than zero), the more important implementation * which will be consulted sooner when seeking for a {@link Contexts#find(net.java.html.BrwsrCtx, java.lang.Class)} * an implementation * @return this builder * @throws IllegalStateException if the position isn't higher than 0 */ public Builder register(Class type, Tech impl, int position) { if (impl == null) { return this; } if (position <= 0) { throw new IllegalStateException(); } this.impl.register(type, impl, position); return this; } /** Generates context based on values previously inserted into * this builder. * * @return new, immutable instance of {@link BrwsrCtx} */ public BrwsrCtx build() { return impl.build(); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy