context/src/main/java/net/java/html/BrwsrCtx.java
author Jaroslav Tulach <jtulach@netbeans.org>
Tue, 26 Aug 2014 18:13:30 +0200
changeset 838 bdc3d696dd4a
parent 790 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.
     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 
    51 /** Represents context where the <code>net.java.html.json.Model</code>
    52  * and other objects
    53  * operate in. The context is usually a particular HTML page in a browser.
    54  * The context is also associated with the actual HTML technology
    55  * in the HTML page - there is likely to be different context for 
    56  * <a href="http://knockoutjs.com">knockout.js</a> and different one
    57  * for <a href="http://angularjs.org">angular</a>.
    58  *
    59  * @author Jaroslav Tulach
    60  */
    61 public final class BrwsrCtx implements Executor {
    62     private static final Logger LOG = Logger.getLogger(BrwsrCtx.class.getName());
    63     private final CtxImpl impl;
    64     private BrwsrCtx(CtxImpl impl) {
    65         this.impl = impl;
    66     }
    67     static {
    68         new CtxAccssr() {
    69             @Override
    70             protected BrwsrCtx newContext(CtxImpl impl) {
    71                 return new BrwsrCtx(impl);
    72             }
    73 
    74             @Override
    75             protected CtxImpl find(BrwsrCtx context) {
    76                 return context.impl;
    77             }
    78         };
    79     }
    80     /** Dummy context without binding to any real browser or technology. 
    81      * Useful for simple unit testing of behavior of various business logic
    82      * code.
    83      */
    84     public static final BrwsrCtx EMPTY = Contexts.newBuilder().build();
    85     
    86     /** currently {@link #execute(java.lang.Runnable) activated context} */
    87     private static final ThreadLocal<BrwsrCtx> CURRENT = new ThreadLocal<BrwsrCtx>();
    88     
    89     /** Seeks for the default context that is associated with the requesting
    90      * class. If no suitable context is found, a warning message is
    91      * printed and {@link #EMPTY} context is returned. One can enter 
    92      * a context by calling {@link #execute(java.lang.Runnable)}.
    93      * 
    94      * @param requestor the class that makes the request
    95      * @return appropriate context for the request
    96      */
    97     public static BrwsrCtx findDefault(Class<?> requestor) {
    98         BrwsrCtx brwsr = CURRENT.get();
    99         if (brwsr != null) {
   100             return brwsr;
   101         }
   102         
   103         org.netbeans.html.context.spi.Contexts.Builder cb = Contexts.newBuilder();
   104         boolean found = Contexts.fillInByProviders(requestor, cb);
   105         if (!found) {
   106             LOG.warning("No browser context found. Returning empty technology!");
   107             return EMPTY;
   108         }
   109         return cb.build();
   110     }
   111 
   112     /** 
   113      * <p>
   114      * Runs provided code in the context of this {@link BrwsrCtx}.
   115      * If there is an {@link Executor} {@link Contexts#find(net.java.html.BrwsrCtx, java.lang.Class)  registered in the context}
   116      * it is used to perform the given code. While the code <code>exec</code>
   117      * is running the value of {@link #findDefault(java.lang.Class)} returns
   118      * <code>this</code>. If the executor supports a single thread execution
   119      * policy, it may execute the runnable later (in such case this method
   120      * returns immediately). If the call to this method is done on the right
   121      * thread, the runnable should be executed synchronously.
   122      * </p>
   123      * <p>
   124      * <b>Example Using a Timer</b>
   125      * </p>
   126 <pre>
   127 <b>public final class</b> Periodicaly <b>extends</b> {@link java.util.TimerTask} {
   128     <b>private final</b> {@link BrwsrCtx} ctx;
   129 
   130     <b>private</b> Periodicaly(BrwsrCtx ctx) {
   131         // remember the browser context and use it later
   132         this.ctx = ctx;
   133     }
   134     
   135     <b>public void</b> run() {
   136         // arrives on wrong thread, needs to be re-scheduled
   137         ctx.{@link #execute(java.lang.Runnable) execute}(new Runnable() {
   138             <b>public void</b> run() {
   139                 // code that needs to run in a browser environment
   140             }
   141         });
   142     }
   143 
   144     // called when your page is ready
   145     <b>public static void</b> onPageLoad(String... args) <b>throws</b> Exception {
   146         // the context at the time of page initialization
   147         BrwsrCtx initialCtx = BrwsrCtx.findDefault(getClass());
   148         // the task that is associated with context 
   149         Periodicaly task = new Periodicaly(initialCtx);
   150         // creates a timer
   151         {@link java.util.Timer} t = new {@link java.util.Timer}("Move the box");
   152         // run the task ever 100ms
   153         t.{@link java.util.Timer#scheduleAtFixedRate(java.util.TimerTask, long, long) scheduleAtFixedRate}(task, 0, 100);
   154     }
   155 }
   156 </pre>    
   157      * 
   158      * @param exec the code to execute
   159      * @since 0.7.6
   160      */
   161     @Override public final void execute(final Runnable exec) {
   162         class Wrap implements Runnable {
   163             @Override
   164             public void run() {
   165                 BrwsrCtx prev = CURRENT.get();
   166                 try {
   167                     CURRENT.set(BrwsrCtx.this);
   168                     exec.run();
   169                 } finally {
   170                     CURRENT.set(prev);
   171                 }
   172             }
   173         }
   174         Wrap w = new Wrap();
   175         Executor runIn = Contexts.find(this, Executor.class);
   176         if (runIn == null) {
   177             w.run();
   178         } else {
   179             runIn.execute(w);
   180         }
   181     }
   182 }
   183