jaroslav@110: /** jaroslav@358: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. jaroslav@110: * jaroslav@551: * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. jaroslav@110: * jaroslav@358: * Oracle and Java are registered trademarks of Oracle and/or its affiliates. jaroslav@358: * Other names may be trademarks of their respective owners. jaroslav@110: * jaroslav@358: * The contents of this file are subject to the terms of either the GNU jaroslav@358: * General Public License Version 2 only ("GPL") or the Common jaroslav@358: * Development and Distribution License("CDDL") (collectively, the jaroslav@358: * "License"). You may not use this file except in compliance with the jaroslav@358: * License. You can obtain a copy of the License at jaroslav@358: * http://www.netbeans.org/cddl-gplv2.html jaroslav@358: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the jaroslav@358: * specific language governing permissions and limitations under the jaroslav@358: * License. When distributing the software, include this License Header jaroslav@358: * Notice in each file and include the License file at jaroslav@358: * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this jaroslav@358: * particular file as subject to the "Classpath" exception as provided jaroslav@358: * by Oracle in the GPL Version 2 section of the License file that jaroslav@358: * accompanied this code. If applicable, add the following below the jaroslav@358: * License Header, with the fields enclosed by brackets [] replaced by jaroslav@358: * your own identifying information: jaroslav@358: * "Portions Copyrighted [year] [name of copyright owner]" jaroslav@358: * jaroslav@358: * Contributor(s): jaroslav@358: * jaroslav@358: * The Original Software is NetBeans. The Initial Developer of the Original jaroslav@551: * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved. jaroslav@358: * jaroslav@358: * If you wish your version of this file to be governed by only the CDDL jaroslav@358: * or only the GPL Version 2, indicate your decision by adding jaroslav@358: * "[Contributor] elects to include this software in this distribution jaroslav@358: * under the [CDDL or GPL Version 2] license." If you do not indicate a jaroslav@358: * single choice of license, a recipient has the option to distribute jaroslav@358: * your version of this file under either the CDDL, the GPL Version 2 or jaroslav@358: * to extend the choice of license to its licensees as provided above. jaroslav@358: * However, if you add GPL Version 2 code and therefore, elected the GPL jaroslav@358: * Version 2 license, then the option applies only if the new code is jaroslav@358: * made subject to such option by the copyright holder. jaroslav@110: */ jtulach@838: package org.netbeans.html.context.spi; jaroslav@110: jtulach@1057: import java.lang.annotation.Documented; jtulach@886: import java.lang.annotation.ElementType; jtulach@886: import java.lang.annotation.Retention; jtulach@886: import java.lang.annotation.RetentionPolicy; jtulach@886: import java.lang.annotation.Target; jtulach@927: import java.util.HashSet; jaroslav@574: import java.util.ServiceLoader; jtulach@927: import java.util.Set; jaroslav@110: import net.java.html.BrwsrCtx; jaroslav@362: import org.netbeans.html.context.impl.CtxImpl; jaroslav@110: jaroslav@538: /** Factory class to assign various technologies jaroslav@538: * to a {@link BrwsrCtx browser context}. Start with {@link #newBuilder()} jaroslav@538: * and then assign technologies with {@link Builder#register(java.lang.Class, java.lang.Object, int)} jaroslav@538: * method. jaroslav@110: * jtulach@655: * @author Jaroslav Tulach jaroslav@110: */ jaroslav@110: public final class Contexts { jaroslav@110: private Contexts() { jaroslav@110: } jaroslav@110: jaroslav@110: /** Creates new, empty builder for creation of {@link BrwsrCtx}. At the jaroslav@534: * end call the {@link Builder#build()} method to generate the context. jtulach@886: * jtulach@886: * @param context instances of various classes or names of {@link Id technologies} jtulach@886: * to be preferred and used in the built {@link BrwsrCtx context}. jtulach@886: * @return new instance of the builder jtulach@886: * @since 1.1 jtulach@886: */ jtulach@886: public static Builder newBuilder(Object... context) { jtulach@886: return new Builder(context); jtulach@886: } jtulach@886: /** Creates new, empty builder for creation of {@link BrwsrCtx}. At the jtulach@886: * end call the {@link Builder#build()} method to generate the context. jtulach@886: * Simply calls {@link #newBuilder(java.lang.Object...) newBuilder(new Object[0])}. jtulach@886: * jaroslav@110: * @return new instance of the builder jaroslav@110: */ jaroslav@110: public static Builder newBuilder() { jtulach@886: return newBuilder(new Object[0]); jaroslav@110: } jaroslav@110: jaroslav@110: /** Seeks for the specified technology in the provided context. jaroslav@110: * jaroslav@110: * @param type of the technology jaroslav@110: * @param context the context to seek in jaroslav@110: * (previously filled with ({@link Builder#register(java.lang.Class, java.lang.Object, int)}) jaroslav@110: * @param technology class that identifies the technology jaroslav@534: * @return the technology in the context or null jaroslav@110: */ jaroslav@110: public static Tech find(BrwsrCtx context, Class technology) { jaroslav@110: return CtxImpl.find(context, technology); jaroslav@110: } jaroslav@110: jaroslav@574: /** Seeks {@link ServiceLoader} for all registered instances of jtulach@838: * {@link Provider} and asks them to {@link Provider#fillContext(org.netbeans.html.context.spi.Contexts.Builder, java.lang.Class) fill jaroslav@574: * the builder}. jaroslav@574: * jaroslav@574: * @param requestor the application class for which to find the context jaroslav@574: * @param cb the context builder to register technologies into jaroslav@574: * @return true, if some instances of the provider were jaroslav@574: * found, false otherwise jaroslav@574: * @since 0.7.6 jaroslav@574: */ jaroslav@574: public static boolean fillInByProviders(Class requestor, Contexts.Builder cb) { jaroslav@574: boolean found = false; jaroslav@574: ClassLoader l; jaroslav@574: try { jaroslav@574: l = requestor.getClassLoader(); jaroslav@574: } catch (SecurityException ex) { jaroslav@574: l = null; jaroslav@574: } jtulach@927: Set> classes = new HashSet>(); jaroslav@574: for (Provider cp : ServiceLoader.load(Provider.class, l)) { jtulach@927: if (!classes.add(cp.getClass())) { jtulach@927: continue; jtulach@927: } jaroslav@574: cp.fillContext(cb, requestor); jaroslav@574: found = true; jaroslav@574: } jaroslav@574: try { jaroslav@574: for (Provider cp : ServiceLoader.load(Provider.class, Provider.class.getClassLoader())) { jtulach@927: if (!classes.add(cp.getClass())) { jtulach@927: continue; jtulach@927: } jaroslav@574: cp.fillContext(cb, requestor); jaroslav@574: found = true; jaroslav@574: } jaroslav@574: } catch (SecurityException ex) { jaroslav@574: if (!found) { jaroslav@574: throw ex; jaroslav@574: } jaroslav@574: } jaroslav@574: if (!found) { jaroslav@574: for (Provider cp : ServiceLoader.load(Provider.class)) { jtulach@927: if (!classes.add(cp.getClass())) { jtulach@927: continue; jtulach@927: } jaroslav@574: cp.fillContext(cb, requestor); jaroslav@574: found = true; jaroslav@574: } jaroslav@574: } jaroslav@574: return found; jaroslav@574: } jtulach@886: jtulach@886: /** Identifies the technologies passed to {@link Builder context builder} jtulach@886: * by a name. Each implementation of a technology jtulach@886: * {@link Builder#register(java.lang.Class, java.lang.Object, int) registered into a context} jtulach@886: * can be annotated with a name (or multiple names). Such implementation jtulach@886: * will later be jtulach@886: * {@link Contexts#fillInByProviders(java.lang.Class, org.netbeans.html.context.spi.Contexts.Builder) preferred during lookup} jtulach@886: * if their name(s) has been requested in when jtulach@886: * {@link Contexts#newBuilder(java.lang.Object...) creating a context}. jtulach@886: * @since 1.1 jtulach@886: */ jtulach@886: @Retention(RetentionPolicy.RUNTIME) jtulach@886: @Target(ElementType.TYPE) jtulach@1057: @Documented jtulach@886: public @interface Id { jtulach@904: /** Identifier(s) for the implementation. jtulach@904: * jtulach@904: * @return one of more identifiers giving this implementation name(s) jtulach@904: */ jtulach@886: public String[] value(); jtulach@886: } jaroslav@574: jaroslav@110: /** Implementors of various HTML technologies should jtulach@790: * register their implementation via org.openide.util.lookup.ServiceProvider, so jtulach@790: * {@link ServiceLoader} can find them, when their JARs are included jaroslav@110: * on the classpath of the running application. jaroslav@110: * jtulach@655: * @author Jaroslav Tulach jaroslav@110: */ jaroslav@110: public static interface Provider { jaroslav@110: jaroslav@110: /** Register into the context if suitable technology is jaroslav@110: * available for the requesting class. jaroslav@110: * The provider should check if its own technology is available in current jaroslav@110: * scope (e.g. proper JDK, proper browser, etc.). The provider jaroslav@110: * can also find the right context depending on requestor's classloader, etc. jaroslav@110: *

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