context/src/main/java/net/java/html/BrwsrCtx.java
author Jaroslav Tulach <jtulach@netbeans.org>
Thu, 29 Oct 2015 16:23:48 +0100
changeset 1013 170c4f72938f
parent 1012 c19904646ed8
child 1053 ed4b25eb66f3
permissions -rw-r--r--
Typo: ever -> every
     1 /**
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3  *
     4  * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
     5  *
     6  * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
     7  * Other names may be trademarks of their respective owners.
     8  *
     9  * The contents of this file are subject to the terms of either the GNU
    10  * General Public License Version 2 only ("GPL") or the Common
    11  * Development and Distribution License("CDDL") (collectively, the
    12  * "License"). You may not use this file except in compliance with the
    13  * License. You can obtain a copy of the License at
    14  * http://www.netbeans.org/cddl-gplv2.html
    15  * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    16  * specific language governing permissions and limitations under the
    17  * License.  When distributing the software, include this License Header
    18  * Notice in each file and include the License file at
    19  * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    20  * particular file as subject to the "Classpath" exception as provided
    21  * by Oracle in the GPL Version 2 section of the License file that
    22  * accompanied this code. If applicable, add the following below the
    23  * License Header, with the fields enclosed by brackets [] replaced by
    24  * your own identifying information:
    25  * "Portions Copyrighted [year] [name of copyright owner]"
    26  *
    27  * Contributor(s):
    28  *
    29  * The Original Software is NetBeans. The Initial Developer of the Original
    30  * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
    31  *
    32  * If you wish your version of this file to be governed by only the CDDL
    33  * or only the GPL Version 2, indicate your decision by adding
    34  * "[Contributor] elects to include this software in this distribution
    35  * under the [CDDL or GPL Version 2] license." If you do not indicate a
    36  * single choice of license, a recipient has the option to distribute
    37  * your version of this file under either the CDDL, the GPL Version 2 or
    38  * to extend the choice of license to its licensees as provided above.
    39  * However, if you add GPL Version 2 code and therefore, elected the GPL
    40  * Version 2 license, then the option applies only if the new code is
    41  * made subject to such option by the copyright holder.
    42  */
    43 package net.java.html;
    44 
    45 import java.util.concurrent.Executor;
    46 import java.util.logging.Logger;
    47 import org.netbeans.html.context.impl.CtxAccssr;
    48 import org.netbeans.html.context.impl.CtxImpl;
    49 import org.netbeans.html.context.spi.Contexts;
    50 import org.netbeans.html.context.spi.Contexts.Id;
    51 
    52 /** Represents context where the <code>net.java.html.json.Model</code>
    53  * and other objects
    54  * operate in. The context is usually a particular HTML page in a browser.
    55  * The context is also associated with the actual HTML technology
    56  * in the HTML page - there is likely to be different context for 
    57  * <a href="http://knockoutjs.com">knockout.js</a> and different one
    58  * for <a href="http://angularjs.org">angular</a>. Since version 1.1
    59  * the content of contexts can be selected by registering
    60  * implementations under specific
    61  * {@link Id technology identifiers} and requesting them during 
    62  * {@link Contexts#newBuilder(java.lang.Object...) construction} of the
    63  * context.
    64  *
    65  * @author Jaroslav Tulach
    66  */
    67 public final class BrwsrCtx implements Executor {
    68     private static final Logger LOG = Logger.getLogger(BrwsrCtx.class.getName());
    69     private final CtxImpl impl;
    70     private BrwsrCtx(CtxImpl impl) {
    71         this.impl = impl;
    72     }
    73     /** currently {@link #execute(java.lang.Runnable) activated context} */
    74     private static final ThreadLocal<BrwsrCtx> CURRENT = new ThreadLocal<BrwsrCtx>();
    75     static {
    76         new CtxAccssr() {
    77             @Override
    78             protected BrwsrCtx newContext(CtxImpl impl) {
    79                 return new BrwsrCtx(impl);
    80             }
    81 
    82             @Override
    83             protected CtxImpl find(BrwsrCtx context) {
    84                 return context.impl;
    85             }
    86         };
    87     }
    88     /** Dummy context without binding to any real browser or technology. 
    89      * Useful for simple unit testing of behavior of various business logic
    90      * code.
    91      */
    92     public static final BrwsrCtx EMPTY = Contexts.newBuilder().build();
    93     
    94     
    95     /** Seeks for the default context that is associated with the requesting
    96      * class. If no suitable context is found, a warning message is
    97      * printed and {@link #EMPTY} context is returned. One can enter 
    98      * a context by calling {@link #execute(java.lang.Runnable)}.
    99      * 
   100      * @param requestor the class that makes the request
   101      * @return appropriate context for the request
   102      */
   103     public static BrwsrCtx findDefault(Class<?> requestor) {
   104         if (requestor == CtxAccssr.class) {
   105             return EMPTY;
   106         }
   107         BrwsrCtx brwsr = CURRENT.get();
   108         if (brwsr != null) {
   109             return brwsr;
   110         }
   111         
   112         org.netbeans.html.context.spi.Contexts.Builder cb = Contexts.newBuilder();
   113         boolean found = Contexts.fillInByProviders(requestor, cb);
   114         if (!found) {
   115             LOG.warning("No browser context found. Returning empty technology!");
   116             return EMPTY;
   117         }
   118         return cb.build();
   119     }
   120 
   121     /** 
   122      * <p>
   123      * Runs provided code in the context of this {@link BrwsrCtx}.
   124      * If there is an {@link Executor} {@link Contexts#find(net.java.html.BrwsrCtx, java.lang.Class)  registered in the context}
   125      * it is used to perform the given code. While the code <code>exec</code>
   126      * is running the value of {@link #findDefault(java.lang.Class)} returns
   127      * <code>this</code>. If the executor supports a single thread execution
   128      * policy, it may execute the runnable later (in such case this method
   129      * returns immediately). If the call to this method is done on the right
   130      * thread, the runnable should be executed synchronously.
   131      * </p>
   132      * <p>
   133      * <b>Example Using a Timer</b>
   134      * </p>
   135 <pre>
   136 <b>public final class</b> Periodicaly <b>extends</b> {@link java.util.TimerTask} {
   137     <b>private final</b> {@link BrwsrCtx} ctx;
   138 
   139     <b>private</b> Periodicaly(BrwsrCtx ctx) {
   140         // remember the browser context and use it later
   141         this.ctx = ctx;
   142     }
   143     
   144     <b>public void</b> run() {
   145         // arrives on wrong thread, needs to be re-scheduled
   146         ctx.{@link #execute(java.lang.Runnable) execute}(new Runnable() {
   147             <b>public void</b> run() {
   148                 // code that needs to run in a browser environment
   149             }
   150         });
   151     }
   152 
   153     // called when your page is ready
   154     <b>public static void</b> onPageLoad(String... args) <b>throws</b> Exception {
   155         // the context at the time of page initialization
   156         BrwsrCtx initialCtx = BrwsrCtx.findDefault(Periodicaly.<b>class</b>);
   157         // the task that is associated with context 
   158         Periodicaly task = new Periodicaly(initialCtx);
   159         // creates a timer
   160         {@link java.util.Timer} t = new {@link java.util.Timer}("Move the box");
   161         // run the task every 100ms
   162         t.{@link java.util.Timer#scheduleAtFixedRate(java.util.TimerTask, long, long) scheduleAtFixedRate}(task, 0, 100);
   163     }
   164 }
   165 </pre>    
   166      * 
   167      * @param exec the code to execute
   168      * @since 0.7.6
   169      */
   170     @Override public final void execute(final Runnable exec) {
   171         class Wrap implements Runnable {
   172             @Override
   173             public void run() {
   174                 BrwsrCtx prev = CURRENT.get();
   175                 try {
   176                     CURRENT.set(BrwsrCtx.this);
   177                     exec.run();
   178                 } finally {
   179                     CURRENT.set(prev);
   180                 }
   181             }
   182         }
   183         Wrap w = new Wrap();
   184         Executor runIn = Contexts.find(this, Executor.class);
   185         if (runIn == null) {
   186             w.run();
   187         } else {
   188             runIn.execute(w);
   189         }
   190     }
   191 }
   192