context/src/main/java/org/netbeans/html/context/spi/Contexts.java
author Jaroslav Tulach <jtulach@netbeans.org>
Tue, 26 Aug 2014 18:13:30 +0200
changeset 838 bdc3d696dd4a
parent 790 context/src/main/java/org/apidesign/html/context/spi/Contexts.java@30f20d9c0986
child 886 88d62267a0b5
permissions -rw-r--r--
During the API review process (bug 246133) the reviewers decided that in order to include html4j to NetBeans Platform, we need to stop using org.apidesign namespace and switch to NetBeans one. Repackaging all SPI packages into org.netbeans.html.smthng.spi.
jaroslav@110
     1
/**
jaroslav@358
     2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
jaroslav@110
     3
 *
jaroslav@551
     4
 * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
jaroslav@110
     5
 *
jaroslav@358
     6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
jaroslav@358
     7
 * Other names may be trademarks of their respective owners.
jaroslav@110
     8
 *
jaroslav@358
     9
 * The contents of this file are subject to the terms of either the GNU
jaroslav@358
    10
 * General Public License Version 2 only ("GPL") or the Common
jaroslav@358
    11
 * Development and Distribution License("CDDL") (collectively, the
jaroslav@358
    12
 * "License"). You may not use this file except in compliance with the
jaroslav@358
    13
 * License. You can obtain a copy of the License at
jaroslav@358
    14
 * http://www.netbeans.org/cddl-gplv2.html
jaroslav@358
    15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
jaroslav@358
    16
 * specific language governing permissions and limitations under the
jaroslav@358
    17
 * License.  When distributing the software, include this License Header
jaroslav@358
    18
 * Notice in each file and include the License file at
jaroslav@358
    19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
jaroslav@358
    20
 * particular file as subject to the "Classpath" exception as provided
jaroslav@358
    21
 * by Oracle in the GPL Version 2 section of the License file that
jaroslav@358
    22
 * accompanied this code. If applicable, add the following below the
jaroslav@358
    23
 * License Header, with the fields enclosed by brackets [] replaced by
jaroslav@358
    24
 * your own identifying information:
jaroslav@358
    25
 * "Portions Copyrighted [year] [name of copyright owner]"
jaroslav@358
    26
 *
jaroslav@358
    27
 * Contributor(s):
jaroslav@358
    28
 *
jaroslav@358
    29
 * The Original Software is NetBeans. The Initial Developer of the Original
jaroslav@551
    30
 * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
jaroslav@358
    31
 *
jaroslav@358
    32
 * If you wish your version of this file to be governed by only the CDDL
jaroslav@358
    33
 * or only the GPL Version 2, indicate your decision by adding
jaroslav@358
    34
 * "[Contributor] elects to include this software in this distribution
jaroslav@358
    35
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
jaroslav@358
    36
 * single choice of license, a recipient has the option to distribute
jaroslav@358
    37
 * your version of this file under either the CDDL, the GPL Version 2 or
jaroslav@358
    38
 * to extend the choice of license to its licensees as provided above.
jaroslav@358
    39
 * However, if you add GPL Version 2 code and therefore, elected the GPL
jaroslav@358
    40
 * Version 2 license, then the option applies only if the new code is
jaroslav@358
    41
 * made subject to such option by the copyright holder.
jaroslav@110
    42
 */
jtulach@838
    43
package org.netbeans.html.context.spi;
jaroslav@110
    44
jaroslav@574
    45
import java.util.ServiceLoader;
jaroslav@110
    46
import net.java.html.BrwsrCtx;
jaroslav@362
    47
import org.netbeans.html.context.impl.CtxImpl;
jaroslav@110
    48
jaroslav@538
    49
/** Factory class to assign various technologies 
jaroslav@538
    50
 * to a {@link BrwsrCtx browser context}. Start with {@link #newBuilder()}
jaroslav@538
    51
 * and then assign technologies with {@link Builder#register(java.lang.Class, java.lang.Object, int)}
jaroslav@538
    52
 * method.
jaroslav@110
    53
 *
jtulach@655
    54
 * @author Jaroslav Tulach
jaroslav@110
    55
 */
jaroslav@110
    56
public final class Contexts {
jaroslav@110
    57
    private Contexts() {
jaroslav@110
    58
    }
jaroslav@110
    59
jaroslav@110
    60
    /** Creates new, empty builder for creation of {@link BrwsrCtx}. At the
jaroslav@534
    61
     * end call the {@link Builder#build()} method to generate the context.
jaroslav@110
    62
     *
jaroslav@110
    63
     * @return new instance of the builder
jaroslav@110
    64
     */
jaroslav@110
    65
    public static Builder newBuilder() {
jaroslav@110
    66
        return new Builder();
jaroslav@110
    67
    }
jaroslav@110
    68
jaroslav@110
    69
    /** Seeks for the specified technology in the provided context.
jaroslav@110
    70
     * 
jaroslav@110
    71
     * @param <Tech> type of the technology
jaroslav@110
    72
     * @param context the context to seek in 
jaroslav@110
    73
     *    (previously filled with ({@link Builder#register(java.lang.Class, java.lang.Object, int)})
jaroslav@110
    74
     * @param technology class that identifies the technology
jaroslav@534
    75
     * @return the technology in the context or <code>null</code>
jaroslav@110
    76
     */
jaroslav@110
    77
    public static <Tech> Tech find(BrwsrCtx context, Class<Tech> technology) {
jaroslav@110
    78
        return CtxImpl.find(context, technology);
jaroslav@110
    79
    }
jaroslav@110
    80
jaroslav@574
    81
    /** Seeks {@link ServiceLoader} for all registered instances of
jtulach@838
    82
     * {@link Provider} and asks them to {@link Provider#fillContext(org.netbeans.html.context.spi.Contexts.Builder, java.lang.Class) fill
jaroslav@574
    83
     * the builder}.
jaroslav@574
    84
     * 
jaroslav@574
    85
     * @param requestor the application class for which to find the context
jaroslav@574
    86
     * @param cb the context builder to register technologies into
jaroslav@574
    87
     * @return <code>true</code>, if some instances of the provider were
jaroslav@574
    88
     *    found, <code>false</code> otherwise
jaroslav@574
    89
     * @since 0.7.6
jaroslav@574
    90
     */
jaroslav@574
    91
    public static boolean fillInByProviders(Class<?> requestor, Contexts.Builder cb) {
jaroslav@574
    92
        boolean found = false;
jaroslav@574
    93
        ClassLoader l;
jaroslav@574
    94
        try {
jaroslav@574
    95
            l = requestor.getClassLoader();
jaroslav@574
    96
        } catch (SecurityException ex) {
jaroslav@574
    97
            l = null;
jaroslav@574
    98
        }
jaroslav@574
    99
        for (Provider cp : ServiceLoader.load(Provider.class, l)) {
jaroslav@574
   100
            cp.fillContext(cb, requestor);
jaroslav@574
   101
            found = true;
jaroslav@574
   102
        }
jaroslav@574
   103
        try {
jaroslav@574
   104
            for (Provider cp : ServiceLoader.load(Provider.class, Provider.class.getClassLoader())) {
jaroslav@574
   105
                cp.fillContext(cb, requestor);
jaroslav@574
   106
                found = true;
jaroslav@574
   107
            }
jaroslav@574
   108
        } catch (SecurityException ex) {
jaroslav@574
   109
            if (!found) {
jaroslav@574
   110
                throw ex;
jaroslav@574
   111
            }
jaroslav@574
   112
        }
jaroslav@574
   113
        if (!found) {
jaroslav@574
   114
            for (Provider cp : ServiceLoader.load(Provider.class)) {
jaroslav@574
   115
                cp.fillContext(cb, requestor);
jaroslav@574
   116
                found = true;
jaroslav@574
   117
            }
jaroslav@574
   118
        }
jaroslav@574
   119
        return found;
jaroslav@574
   120
    }
jaroslav@574
   121
jaroslav@110
   122
    /** Implementors of various HTML technologies should
jtulach@790
   123
     * register their implementation via <code>org.openide.util.lookup.ServiceProvider</code>, so
jtulach@790
   124
     * {@link ServiceLoader} can find them, when their JARs are included
jaroslav@110
   125
     * on the classpath of the running application.
jaroslav@110
   126
     *
jtulach@655
   127
     * @author Jaroslav Tulach
jaroslav@110
   128
     */
jaroslav@110
   129
    public static interface Provider {
jaroslav@110
   130
jaroslav@110
   131
        /** Register into the context if suitable technology is
jaroslav@110
   132
         * available for the requesting class.
jaroslav@110
   133
         * The provider should check if its own technology is available in current
jaroslav@110
   134
         * scope (e.g. proper JDK, proper browser, etc.). The provider
jaroslav@110
   135
         * can also find the right context depending on requestor's classloader, etc.
jaroslav@110
   136
         * <p>
jaroslav@110
   137
         * Providers should use {@link Builder} to enrich appropriately
jaroslav@110
   138
         * the context.
jaroslav@110
   139
         *
jaroslav@110
   140
         * @param context the context builder to fill with technologies
jaroslav@110
   141
         * @param requestor the application class requesting access the the HTML page
jaroslav@110
   142
         * @see BrwsrCtx#findDefault(java.lang.Class)
jaroslav@110
   143
         */
jaroslav@110
   144
        void fillContext(Builder context, Class<?> requestor);
jaroslav@110
   145
    }
jaroslav@110
   146
jaroslav@110
   147
    /** Support for providers of new {@link BrwsrCtx}. Providers of different
jaroslav@110
   148
     * technologies should be of particular interest in this class. End users
jaroslav@110
   149
     * designing their application with existing technologies should rather
jaroslav@110
   150
     * point their attention to {@link BrwsrCtx} and co.
jaroslav@110
   151
     *
jtulach@655
   152
     * @author Jaroslav Tulach
jaroslav@110
   153
     */
jaroslav@110
   154
    public static final class Builder {
jaroslav@256
   155
        private final CtxImpl impl = new CtxImpl();
jaroslav@110
   156
jaroslav@110
   157
        Builder() {
jaroslav@110
   158
        }
jaroslav@110
   159
        
jaroslav@110
   160
        /** Registers new technology into the context. Each technology is
jaroslav@110
   161
         * exactly identified by its implementation class and can be associated
jaroslav@110
   162
         * with (positive) priority. In case of presence of multiple technologies
jaroslav@110
   163
         * with the same class, the one with higher lower priority takes precedence.
jaroslav@256
   164
         * @param <Tech> type of technology to register
jaroslav@256
   165
         * @param type the real class of the technology type
jaroslav@256
   166
         * @param impl an instance of the technology class
jaroslav@256
   167
         * @param position the lower position, the more important implementation 
jaroslav@256
   168
         *    which will be consulted sooner when seeking for a {@link Contexts#find(net.java.html.BrwsrCtx, java.lang.Class)}
jaroslav@256
   169
         *    an implementation
jaroslav@256
   170
         * @return this builder
jaroslav@110
   171
         */
jaroslav@256
   172
        public <Tech> Builder register(Class<Tech> type, Tech impl, int position) {
jaroslav@589
   173
            if (impl == null) {
jaroslav@589
   174
                return this;
jaroslav@589
   175
            }
jaroslav@256
   176
            if (position <= 0) {
jaroslav@110
   177
                throw new IllegalStateException();
jaroslav@110
   178
            }
jaroslav@256
   179
            this.impl.register(type, impl, position);
jaroslav@110
   180
            return this;
jaroslav@110
   181
        }
jaroslav@110
   182
jaroslav@110
   183
        /** Generates context based on values previously inserted into
jaroslav@110
   184
         * this builder.
jaroslav@110
   185
         *
jaroslav@110
   186
         * @return new, immutable instance of {@link BrwsrCtx}
jaroslav@110
   187
         */
jaroslav@110
   188
        public BrwsrCtx build() {
jaroslav@110
   189
            return impl.build();
jaroslav@110
   190
        }
jaroslav@110
   191
    }
jaroslav@110
   192
}