context/src/main/java/net/java/html/BrwsrCtx.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Fri, 13 Sep 2013 11:50:42 +0200
branchbatchnotify
changeset 301 74e862ea824e
parent 167 10005a498972
permissions -rw-r--r--
Context should be shared per classloader
     1 /**
     2  * HTML via Java(tm) Language Bindings
     3  * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     4  *
     5  * This program is free software: you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation, version 2 of the License.
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details. apidesign.org
    13  * designates this particular file as subject to the
    14  * "Classpath" exception as provided by apidesign.org
    15  * in the License file that accompanied this code.
    16  *
    17  * You should have received a copy of the GNU General Public License
    18  * along with this program. Look for COPYING file in the top folder.
    19  * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
    20  */
    21 package net.java.html;
    22 
    23 import java.util.HashMap;
    24 import java.util.Map;
    25 import java.util.ServiceLoader;
    26 import org.apidesign.html.context.impl.CtxAccssr;
    27 import org.apidesign.html.context.impl.CtxImpl;
    28 import org.apidesign.html.context.spi.Contexts;
    29 
    30 /** Represents context where the <code>net.java.html.json.Model</code>
    31  * and other objects
    32  * operate in. The context is usually a particular HTML page in a browser.
    33  * The context is also associated with the actual HTML technology
    34  * in the HTML page - there is likely to be different context for 
    35  * <a href="http://knockoutjs.com">knockout.js</a> and different one
    36  * for <a href="http://angularjs.org">angular</a>.
    37  *
    38  * @author Jaroslav Tulach <jtulach@netbeans.org>
    39  */
    40 public final class BrwsrCtx {
    41     private final CtxImpl impl;
    42     private BrwsrCtx(CtxImpl impl) {
    43         this.impl = impl;
    44     }
    45     static {
    46         new CtxAccssr() {
    47             @Override
    48             protected BrwsrCtx newContext(CtxImpl impl) {
    49                 return new BrwsrCtx(impl);
    50             }
    51 
    52             @Override
    53             protected CtxImpl find(BrwsrCtx context) {
    54                 return context.impl;
    55             }
    56         };
    57     }
    58     /** Dummy context without binding to any real browser or technology. 
    59      * Useful for simple unit testing of behavior of various business logic
    60      * code.
    61      */
    62     public static final BrwsrCtx EMPTY = Contexts.newBuilder().build();
    63     /** map of known classloaders and their contexts */
    64     private static final Map<ClassLoader,BrwsrCtx> CTXS = new HashMap<ClassLoader, BrwsrCtx>();
    65     
    66     /** Seeks for the default context that is associated with the requesting
    67      * class. If no suitable context is found, a warning message is
    68      * printed and {@link #EMPTY} context is returned.
    69      * 
    70      * @param requestor the class that makes the request
    71      * @return appropriate context for the request
    72      */
    73     public static BrwsrCtx findDefault(Class<?> requestor) {
    74         org.apidesign.html.context.spi.Contexts.Builder cb = Contexts.newBuilder();
    75         boolean found = false;
    76         
    77         ClassLoader l;
    78         try {
    79             l = requestor.getClassLoader();
    80         } catch (SecurityException ex) {
    81             l = null;
    82         }
    83         
    84         synchronized (CTXS) {
    85             BrwsrCtx c = CTXS.get(l);
    86             if (c != null) {
    87                 return c;
    88             }
    89         }
    90         
    91         for (org.apidesign.html.context.spi.Contexts.Provider cp : ServiceLoader.load(
    92             org.apidesign.html.context.spi.Contexts.Provider.class, l
    93         )) {
    94             cp.fillContext(cb, requestor);
    95             found = true;
    96         }
    97         try {
    98             for (org.apidesign.html.context.spi.Contexts.Provider cp : ServiceLoader.load(org.apidesign.html.context.spi.Contexts.Provider.class, org.apidesign.html.context.spi.Contexts.Provider.class.getClassLoader())) {
    99                 cp.fillContext(cb, requestor);
   100                 found = true;
   101             }
   102         } catch (SecurityException ex) {
   103             if (!found) {
   104                 throw ex;
   105             }
   106             // if we have some data from regular provides, go on
   107         }
   108         if (!found) {
   109             // XXX: print out a warning
   110             return EMPTY;
   111         }
   112         BrwsrCtx c = cb.build();
   113         
   114         synchronized (CTXS) {
   115             CTXS.put(l, c);
   116         }
   117         return c;
   118     }
   119     
   120 }