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