http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/equinox-agentclass-hook/src/main/resources/hookconfigurators.properties ---------------------------------------------------------------------- diff --git a/equinox-agentclass-hook/src/main/resources/hookconfigurators.properties b/equinox-agentclass-hook/src/main/resources/hookconfigurators.properties new file mode 100644 index 0000000..d9fe69e --- /dev/null +++ b/equinox-agentclass-hook/src/main/resources/hookconfigurators.properties @@ -0,0 +1,44 @@ +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. +# +# Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. +# +# Oracle and Java are registered trademarks of Oracle and/or its affiliates. +# Other names may be trademarks of their respective owners. +# +# The contents of this file are subject to the terms of either the GNU +# General Public License Version 2 only ("GPL") or the Common +# Development and Distribution License("CDDL") (collectively, the +# "License"). You may not use this file except in compliance with the +# License. You can obtain a copy of the License at +# http://www.netbeans.org/cddl-gplv2.html +# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the +# specific language governing permissions and limitations under the +# License. When distributing the software, include this License Header +# Notice in each file and include the License file at +# nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the GPL Version 2 section of the License file that +# accompanied this code. If applicable, add the following below the +# License Header, with the fields enclosed by brackets [] replaced by +# your own identifying information: +# "Portions Copyrighted [year] [name of copyright owner]" +# +# Contributor(s): +# +# The Original Software is NetBeans. The Initial Developer of the Original +# Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. +# +# If you wish your version of this file to be governed by only the CDDL +# or only the GPL Version 2, indicate your decision by adding +# "[Contributor] elects to include this software in this distribution +# under the [CDDL or GPL Version 2] license." If you do not indicate a +# single choice of license, a recipient has the option to distribute +# your version of this file under either the CDDL, the GPL Version 2 or +# to extend the choice of license to its licensees as provided above. +# However, if you add GPL Version 2 code and therefore, elected the GPL +# Version 2 license, then the option applies only if the new code is +# made subject to such option by the copyright holder. +# + +hook.configurators=org.netbeans.html.equinox.agentclass.AgentHook
http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/geo/pom.xml ---------------------------------------------------------------------- diff --git a/geo/pom.xml b/geo/pom.xml new file mode 100644 index 0000000..741c6d3 --- /dev/null +++ b/geo/pom.xml @@ -0,0 +1,94 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + + Copyright 2013-2016 Oracle and/or its affiliates. All rights reserved. + + Oracle and Java are registered trademarks of Oracle and/or its affiliates. + Other names may be trademarks of their respective owners. + + The contents of this file are subject to the terms of either the GNU + General Public License Version 2 only ("GPL") or the Common + Development and Distribution License("CDDL") (collectively, the + "License"). You may not use this file except in compliance with the + License. You can obtain a copy of the License at + http://www.netbeans.org/cddl-gplv2.html + or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + specific language governing permissions and limitations under the + License. When distributing the software, include this License Header + Notice in each file and include the License file at + nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + particular file as subject to the "Classpath" exception as provided + by Oracle in the GPL Version 2 section of the License file that + accompanied this code. If applicable, add the following below the + License Header, with the fields enclosed by brackets [] replaced by + your own identifying information: + "Portions Copyrighted [year] [name of copyright owner]" + + Contributor(s): + + The Original Software is NetBeans. The Initial Developer of the Original + Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + + If you wish your version of this file to be governed by only the CDDL + or only the GPL Version 2, indicate your decision by adding + "[Contributor] elects to include this software in this distribution + under the [CDDL or GPL Version 2] license." If you do not indicate a + single choice of license, a recipient has the option to distribute + your version of this file under either the CDDL, the GPL Version 2 or + to extend the choice of license to its licensees as provided above. + However, if you add GPL Version 2 code and therefore, elected the GPL + Version 2 license, then the option applies only if the new code is + made subject to such option by the copyright holder. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.netbeans.html</groupId> + <artifactId>pom</artifactId> + <version>2.0-SNAPSHOT</version> + </parent> + <groupId>org.netbeans.html</groupId> + <artifactId>net.java.html.geo</artifactId> + <version>2.0-SNAPSHOT</version> + <packaging>bundle</packaging> + <name>Geolocation API</name> + <url>http://maven.apache.org</url> + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <publicPackages>net.java.html.geo,org.netbeans.html.geo.spi</publicPackages> + </properties> + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + </plugin> + <plugin> + <groupId>org.netbeans.html</groupId> + <artifactId>html4j-maven-plugin</artifactId> + </plugin> + </plugins> + </build> + <dependencies> + <dependency> + <groupId>org.testng</groupId> + <artifactId>testng</artifactId> + </dependency> + <dependency> + <groupId>org.netbeans.api</groupId> + <artifactId>org-openide-util-lookup</artifactId> + <type>jar</type> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.netbeans.html</groupId> + <artifactId>net.java.html.boot</artifactId> + <version>${project.version}</version> + <type>jar</type> + </dependency> + </dependencies> + <description>Find out where your Java program running in an HTML page is!</description> +</project> http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/geo/src/main/java/net/java/html/geo/OnLocation.java ---------------------------------------------------------------------- diff --git a/geo/src/main/java/net/java/html/geo/OnLocation.java b/geo/src/main/java/net/java/html/geo/OnLocation.java new file mode 100644 index 0000000..07dc8a6 --- /dev/null +++ b/geo/src/main/java/net/java/html/geo/OnLocation.java @@ -0,0 +1,96 @@ +/** + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package net.java.html.geo; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** Generates a handle which can configure, {@link Position.Handle#start() start} + * and {@link Position.Handle#stop() stop} requests for obtaining current + * location of the application/device/user. Put the {@link OnLocation} annotation + * on top of a (non-private) method in your class which takes one argument + * {@link Position}. Based on name of your method (unless a class name is + * directly specified via {@link #className()} attribute) a handle class is + * generated. For example if your method name is <code>callMeWhenYouKnowWhereYouAre</code> + * a package private class <code>CallMeWhenYouKnowWhereYouAreHandle</code> will + * be generated in the same package. One can use its <code>createQuery</code> + * and <code>createWatch</code> static method to get one time/repeated time + * instance of a {@link Position.Handle handle}. After configuring the + * {@link Position.Handle handle} via its setter methods, one can + * {@link Position.Handle#start() start} the location request. + * <p> + * In case something goes wrong a method in the same class named {@link #onError()} + * can be specified (should take one {@link Exception} parameter). + * <p> + * The overall behavior of the system mimics <a href="http://www.w3.org/TR/geolocation-API/"> + * W3C's Geolocation API</a>. + * + * @author Jaroslav Tulach + */ +@Retention(RetentionPolicy.SOURCE) +@Target(ElementType.METHOD) +public @interface OnLocation { + /** Name of the {@link Position.Handle handle} class to generate. By + * default the name is derived from the name of annotated method by + * capitalizing the first character and appending <code>Handle</code>. + * <p> + * The generated class contains two static methods: <code>createQuery</code> + * and <code>createWatch</code> which take no parameters if this method + * is static or one parameter (of this class) if this method is instance + * one. Both static methods return {@link Position.Handle}. + * + * @return string suitable for a new class in the same package + */ + public String className() default ""; + + /** Name of a method in this class which should be called in case of + * an error. The method has to be non-private and take {@link Exception} + * parameter. If this method is not specified, the exception is just + * printed to console. + * + * @return name of method in this class + */ + public String onError() default ""; +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/geo/src/main/java/net/java/html/geo/Position.java ---------------------------------------------------------------------- diff --git a/geo/src/main/java/net/java/html/geo/Position.java b/geo/src/main/java/net/java/html/geo/Position.java new file mode 100644 index 0000000..4f2edb8 --- /dev/null +++ b/geo/src/main/java/net/java/html/geo/Position.java @@ -0,0 +1,383 @@ +/** + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package net.java.html.geo; + +import java.util.Collections; +import java.util.ServiceLoader; +import java.util.logging.Level; +import java.util.logging.Logger; +import net.java.html.BrwsrCtx; +import org.netbeans.html.context.spi.Contexts; +import org.netbeans.html.geo.impl.Accessor; +import org.netbeans.html.geo.impl.JsGLProvider; +import org.netbeans.html.geo.spi.GLProvider; + +/** Class that represents a geolocation position provided as a callback + * to {@link Handle#onLocation(net.java.html.geo.Position)} method. The + * class getters mimic closely the structure of the position object as + * specified by <a href="http://www.w3.org/TR/geolocation-API/"> + * W3C's Geolocation API</a>. + * + * @author Jaroslav Tulach + */ +public final class Position { + static final Logger LOG = Logger.getLogger(Position.class.getName()); + private final long timestamp; + private final Coordinates coords; + + public Position(long timestamp, Coordinates coords) { + this.timestamp = timestamp; + this.coords = coords; + } + + /** The actual location of the position. + * @return non-null coordinates + */ + public Coordinates getCoords() { + return coords; + } + + /** The time when the position has been recorded. + * @return time in milliseconds since era (e.g. Jan 1, 1970). + */ + public long getTimestamp() { + return timestamp; + } + + /** Actual location of a {@link Position}. + * Mimics closely <a href="http://www.w3.org/TR/geolocation-API/"> + * W3C's Geolocation API</a>. + */ + public static abstract class Coordinates { + protected Coordinates() { + if (!getClass().getName().equals("org.netbeans.html.geo.spi.CoordImpl")) { + throw new IllegalStateException(); + } + } + + /** + * @return geographic coordinate specified in decimal degrees. + */ + public abstract double getLatitude(); + + /** + * @return geographic coordinate specified in decimal degrees. + */ + public abstract double getLongitude(); + + /** + * The accuracy attribute denotes the accuracy level of the latitude + * and longitude coordinates. It is specified in meters. + * The value of the accuracy attribute must be a non-negative number. + * + * @return accuracy in meters + */ + public abstract double getAccuracy(); + + /** Denotes the height of the position, specified in meters above the ellipsoid. + * If the implementation cannot provide altitude information, + * the value of this attribute must be null. + * @return value in meters, may return null, if the information is not available + */ + public abstract Double getAltitude(); + + /** The altitude accuracy is specified in meters. + * If the implementation cannot provide altitude information, + * the value of this attribute must be null. Otherwise, the value + * must be a non-negative real number. + * @return value in meters; may return null, if the information is not available + */ + public abstract Double getAltitudeAccuracy(); + + /** Denotes the direction of travel of the device and + * is specified in degrees + * counting clockwise relative to the true north. + * + * @return value from 0 to 360 - may return <code>null</code>, + * if the information is not available + */ + public abstract Double getHeading(); + + /** Denotes the magnitude of the horizontal component of the + * device's current velocity and is specified in meters per second. + * + * @return may return null, if the information is not available + */ + public abstract Double getSpeed(); + } // end of Coordinates + + /** Rather than subclassing this class directly consider using {@link OnLocation} + * annotation. Such annotation will generate a subclass for you automatically + * with two static methods <code>createQuery</code> and <code>createWatch</code> + * which can be used to obtain instance of this class. + */ + public static abstract class Handle { + private final boolean oneTime; + private boolean enableHighAccuracy; + private long timeout; + private long maximumAge; + volatile JsH<?> handle; + + /** Creates new instance of this handle. + * + * @param oneTime <code>true</code> if the handle represents one time + * <em>query</em>. <code>false</code> if it represents a <em>watch</em> + */ + protected Handle(boolean oneTime) { + super(); + this.oneTime = oneTime; + } + + /** Callback from the implementation when a (new) position has been + * received and identified + * @param p the position + * @throws Throwable if an exception is thrown, it will be logged by the system + */ + protected abstract void onLocation(Position p) throws Throwable; + + /** Callback when an error occurs. + * @param ex the exception describing what went wrong + * @throws Throwable if an exception is thrown, it will be logged by the system + */ + protected abstract void onError(Exception ex) throws Throwable; + + /** Check whether the location API is supported. + * @return true, if one can call {@link #start}. + */ + public final boolean isSupported() { + JsH<?> p = seekProviders(null, null); + if (p != null) { + p.stop(); + return true; + } + return false; + } + + /** Turns on high accuracy mode as specified by the + * <a href="http://www.w3.org/TR/2012/PRÂgeolocationÂAPIÂ20120510/"> + * W3C's Geolocation API</a>. By default the mode is disabled. + * @param enable <code>true</code> or <code>false</code> + */ + public final void setHighAccuracy(boolean enable) { + this.enableHighAccuracy = enable; + } + + /** The amount of milliseconds to wait for a result. + * By default infinity. + * @param timeout time in milliseconds to wait for a result. + */ + public final void setTimeout(long timeout) { + this.timeout = timeout; + } + + /** Sets maximum age of cached results which are acceptable to be + * returned. By default maximum age is set to zero. + * @param age time in milliseconds of acceptable cached results + */ + public final void setMaximumAge(long age) { + this.maximumAge = age; + } + + /** Initializes the <em>query</em> or <em>watch</em> request(s) and + * returns immediately. Has no effect if the query has already been + * started. If a problem appears while starting the system, + * it is immediately reported via the {@link #onError(java.lang.Exception)} + * callback. For example, if the {@link #isSupported()} method + * returns <code>false</code> an IllegalStateException is created + * and sent to the {@link #onError(java.lang.Exception) callback} method. + */ + public final void start() { + if (handle != null) { + return; + } + + Exception[] problem = { null }; + StringBuilder sb = new StringBuilder(); + sb.append("["); + JsH<?> h = seekProviders(sb, problem); + sb.append("\n]"); + try { + if (problem[0] != null) { + onError(problem[0]); + return; + } + if (h == null) { + onError(new IllegalStateException("geolocation API not supported. Among providers: " + sb)); + } + synchronized (this) { + if (handle != null) { + onError(new IllegalStateException("Parallel request")); + } + handle = h; + } + } catch (Throwable thr) { + LOG.log(Level.INFO, "Problems delivering onError report", thr); + } + } + + private JsH<?> seekProviders(StringBuilder sb, Exception[] problem) { + BrwsrCtx ctx = BrwsrCtx.findDefault(getClass()); + JsH<?> h = seekProviders(Contexts.find(ctx, GLProvider.class), null, sb, problem); + if (h == null) { + h = seekProviders(null, ServiceLoader.load(GLProvider.class), sb, problem); + } + if (h == null) { + h = seekProviders(new JsGLProvider(), null, sb, problem); + } + return h; + } + + private JsH<?> seekProviders( + GLProvider single, Iterable<GLProvider> set, + StringBuilder sb, Exception[] problem + ) { + if (set == null) { + if (single == null) { + return null; + } + set = Collections.singleton(single); + } + JsH<?> h = null; + for (GLProvider<?,?> p : set) { + if (sb != null) { + if (sb.length() > 1) { + sb.append(','); + } + sb.append("\n ").append(p.getClass().getName()); + } + try { + h = createHandle(p); + } catch (Exception ex) { + LOG.log(Level.INFO, "Problems when starting " + p.getClass().getName(), ex); + if (problem != null && problem[0] == null) { + problem[0] = ex; + } + } + if (h != null) { + break; + } + } + return h; + } + + /** Stops all pending requests. After this call no further callbacks + * can be obtained. Does nothing if no query or watch was in progress. + */ + public final void stop() { + JsH h; + synchronized (this) { + h = handle; + if (h == null) { + return; + } + handle = null; + } + h.stop(); + } + + private <Watch> JsH<Watch> createHandle(GLProvider<?,Watch> p) { + JsH<Watch> temp = new JsH<Watch>(p); + return temp.watch == null ? null : temp; + } + + private final class JsH<Watch> extends Accessor { + private final Watch watch; + private final GLProvider<?, Watch> provider; + + public JsH(GLProvider<?, Watch> p) { + super(true); + this.watch = Accessor.SPI.start(p, this, oneTime, enableHighAccuracy, timeout, maximumAge); + this.provider = p; + } + + @Override + public void onLocation(Position position) { + if (handle != this) { + return; + } + if (oneTime) { + stop(); + } + try { + Handle.this.onLocation(position); + } catch (Throwable ex) { + LOG.log(Level.SEVERE, null, ex); + } + } + + @Override + public void onError(Exception err) { + if (handle != this) { + return; + } + if (oneTime) { + stop(); + } + try { + Handle.this.onError(err); + } catch (Throwable ex) { + LOG.log(Level.SEVERE, null, ex); + } + } + + protected final void stop() { + Accessor.SPI.stop(provider, watch); + } + + @Override + public <Watch> Watch start( + GLProvider<?, Watch> p, Accessor peer, + boolean oneTime, boolean enableHighAccuracy, + long timeout, long maximumAge + ) { + throw new UnsupportedOperationException(); + } + + @Override + public <Watch> void stop(GLProvider<?, Watch> p, Watch w) { + throw new UnsupportedOperationException(); + } + + } // end of JsH + } +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/geo/src/main/java/net/java/html/geo/doc-files/GeoDuke.png ---------------------------------------------------------------------- diff --git a/geo/src/main/java/net/java/html/geo/doc-files/GeoDuke.png b/geo/src/main/java/net/java/html/geo/doc-files/GeoDuke.png new file mode 100644 index 0000000..56826a1 Binary files /dev/null and b/geo/src/main/java/net/java/html/geo/doc-files/GeoDuke.png differ http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/geo/src/main/java/net/java/html/geo/package.html ---------------------------------------------------------------------- diff --git a/geo/src/main/java/net/java/html/geo/package.html b/geo/src/main/java/net/java/html/geo/package.html new file mode 100644 index 0000000..bf9c6ab --- /dev/null +++ b/geo/src/main/java/net/java/html/geo/package.html @@ -0,0 +1,74 @@ +<!-- + + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + + Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + + Oracle and Java are registered trademarks of Oracle and/or its affiliates. + Other names may be trademarks of their respective owners. + + The contents of this file are subject to the terms of either the GNU + General Public License Version 2 only ("GPL") or the Common + Development and Distribution License("CDDL") (collectively, the + "License"). You may not use this file except in compliance with the + License. You can obtain a copy of the License at + http://www.netbeans.org/cddl-gplv2.html + or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + specific language governing permissions and limitations under the + License. When distributing the software, include this License Header + Notice in each file and include the License file at + nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + particular file as subject to the "Classpath" exception as provided + by Oracle in the GPL Version 2 section of the License file that + accompanied this code. If applicable, add the following below the + License Header, with the fields enclosed by brackets [] replaced by + your own identifying information: + "Portions Copyrighted [year] [name of copyright owner]" + + Contributor(s): + + The Original Software is NetBeans. The Initial Developer of the Original + Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + + If you wish your version of this file to be governed by only the CDDL + or only the GPL Version 2, indicate your decision by adding + "[Contributor] elects to include this software in this distribution + under the [CDDL or GPL Version 2] license." If you do not indicate a + single choice of license, a recipient has the option to distribute + your version of this file under either the CDDL, the GPL Version 2 or + to extend the choice of license to its licensees as provided above. + However, if you add GPL Version 2 code and therefore, elected the GPL + Version 2 license, then the option applies only if the new code is + made subject to such option by the copyright holder. + +--> +<!DOCTYPE html> +<html> + <head> + <title>Geolocation API for Java</title> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <meta name="viewport" content="width=device-width"> + </head> + <body> + <span id="geoduke"></span> + <div> + HTML Geo API for Java provides <a href="OnLocation.html">annotation based way</a> of + obtaining geolocation information from a browser or any other + device capable of providing it. + The primary way to use this API is to + create a non-private method and annotate it with <a href="OnLocation.html">@OnLocation</a> + annotation. + </div> + <img src="doc-files/GeoDuke.png" alt="Illustrative picture"/> + <script type="text/javascript"> + var s = document.getElementById("geoduke"); + var i = document.createElement("img"); + i.width = 120; + i.height = 60; + i.align = 'right'; + i.src="doc-files/GeoDuke.png"; + i.alt="Illustrative picture"; + s.appendChild(i); + </script> + </body> +</html> http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/geo/src/main/java/org/netbeans/html/geo/impl/Accessor.java ---------------------------------------------------------------------- diff --git a/geo/src/main/java/org/netbeans/html/geo/impl/Accessor.java b/geo/src/main/java/org/netbeans/html/geo/impl/Accessor.java new file mode 100644 index 0000000..e394c95 --- /dev/null +++ b/geo/src/main/java/org/netbeans/html/geo/impl/Accessor.java @@ -0,0 +1,76 @@ +/** + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package org.netbeans.html.geo.impl; + +import net.java.html.geo.Position; +import org.netbeans.html.geo.spi.GLProvider; + +/** Connection between API and SPI parts of the module. + * + * @author Jaroslav Tulach <[email protected]> + */ +public abstract class Accessor { + public static Accessor SPI; + static { + JsGLProvider initGLProviderClass = new JsGLProvider(); + } + + protected Accessor(boolean api) { + if (!api) { + assert SPI == null; + SPI = this; + } + } + + public abstract <Watch> Watch start( + GLProvider<?, Watch> p, Accessor peer, + boolean oneTime, boolean enableHighAccuracy, + long timeout, long maximumAge + ); + + public abstract <Watch> void stop(GLProvider<?, Watch> p, Watch w); + + public abstract void onError(Exception ex); + + public abstract void onLocation(Position position); +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/geo/src/main/java/org/netbeans/html/geo/impl/GeoProcessor.java ---------------------------------------------------------------------- diff --git a/geo/src/main/java/org/netbeans/html/geo/impl/GeoProcessor.java b/geo/src/main/java/org/netbeans/html/geo/impl/GeoProcessor.java new file mode 100644 index 0000000..ff2635e --- /dev/null +++ b/geo/src/main/java/org/netbeans/html/geo/impl/GeoProcessor.java @@ -0,0 +1,290 @@ +/** + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package org.netbeans.html.geo.impl; + +import java.io.IOException; +import java.io.Writer; +import java.util.List; +import java.util.Locale; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.Processor; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.annotation.processing.SupportedSourceVersion; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.TypeMirror; +import javax.tools.Diagnostic; +import javax.tools.JavaFileObject; +import net.java.html.geo.OnLocation; +import net.java.html.geo.Position; +import net.java.html.geo.Position.Handle; +import org.openide.util.lookup.ServiceProvider; + +/** Annotation processor to generate callbacks from {@link Handle} class. + * + * @author Jaroslav Tulach + */ +@ServiceProvider(service=Processor.class) +@SupportedSourceVersion(SourceVersion.RELEASE_6) +@SupportedAnnotationTypes({ + "net.java.html.geo.OnLocation" +}) +public final class GeoProcessor extends AbstractProcessor { + private static final Logger LOG = Logger.getLogger(GeoProcessor.class.getName()); + @Override + public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { + boolean ok = true; + for (Element e : roundEnv.getElementsAnnotatedWith(OnLocation.class)) { + if (!processLocation(e)) { + ok = false; + } + } + return ok; + } + + private void error(String msg, Element e) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg, e); + } + + private boolean processLocation(Element e) { + if (e.getKind() != ElementKind.METHOD) { + return false; + } + ExecutableElement me = (ExecutableElement) e; + OnLocation ol = e.getAnnotation(OnLocation.class); + if (ol == null) { + return true; + } + if (me.getModifiers().contains(Modifier.PRIVATE)) { + error("Method annotated by @OnLocation cannot be private", e); + return false; + } + TypeMirror positionClass = processingEnv.getElementUtils().getTypeElement(Position.class.getName()).asType(); + final List<? extends VariableElement> params = me.getParameters(); + if (params.size() < 1 || !params.get(0).asType().equals(positionClass)) { + error("Method annotated by @OnLocation first argument must be net.java.html.geo.Position!", e); + return false; + } + String className = ol.className(); + if (className.isEmpty()) { + String n = e.getSimpleName().toString(); + if (n.isEmpty()) { + error("Empty method name", e); + return false; + } + final String firstLetter = n.substring(0, 1).toUpperCase(Locale.ENGLISH); + className = firstLetter + n.substring(1) + "Handle"; + } + TypeElement te = (TypeElement)e.getEnclosingElement(); + PackageElement pe = (PackageElement) te.getEnclosingElement(); + final String pkg = pe.getQualifiedName().toString(); + final String fqn = pkg + "." + className; + final boolean isStatic = me.getModifiers().contains(Modifier.STATIC); + String sep; + try { + JavaFileObject fo = processingEnv.getFiler().createSourceFile(fqn, e); + Writer w = fo.openWriter(); + w.append("package ").append(pkg).append(";\n"); + w.append("class ").append(className).append(" extends net.java.html.geo.Position.Handle {\n"); + if (!isStatic) { + w.append(" private final ").append(te.getSimpleName()).append(" $i;\n"); + } + for (int i = 1; i < params.size(); i++) { + final VariableElement p = params.get(i); + w.append(" private final ").append(p.asType().toString()).append(" ").append(p.getSimpleName()).append(";\n"); + } + w.append(" private ").append(className).append("(boolean oneTime"); + w.append(", ").append(te.getSimpleName()).append(" i"); + for (int i = 1; i < params.size(); i++) { + final VariableElement p = params.get(i); + w.append(", ").append(p.asType().toString()).append(" ").append(p.getSimpleName()); + } + w.append(") {\n super(oneTime);\n"); + if (!isStatic) { + w.append(" this.$i = i;\n"); + } + for (int i = 1; i < params.size(); i++) { + final VariableElement p = params.get(i); + w.append(" this.").append(p.getSimpleName()).append(" = ").append(p.getSimpleName()).append(";\n"); + } + w.append("}\n"); + w.append(" static net.java.html.geo.Position.Handle createQuery("); + String inst; + if (!isStatic) { + w.append(te.getSimpleName()).append(" instance"); + inst = "instance"; + sep = ", "; + } else { + inst = "null"; + sep = ""; + } + for (int i = 1; i < params.size(); i++) { + final VariableElement p = params.get(i); + w.append(sep).append(p.asType().toString()).append(" ").append(p.getSimpleName()); + sep = ", "; + } + w.append(") { return new ").append(className).append("(true, ").append(inst); + for (int i = 1; i < params.size(); i++) { + final VariableElement p = params.get(i); + w.append(", ").append(p.getSimpleName()); + } + w.append("); }\n"); + w.append(" static net.java.html.geo.Position.Handle createWatch("); + if (!isStatic) { + w.append(te.getSimpleName()).append(" instance"); + sep = ", "; + } else { + sep = ""; + } + for (int i = 1; i < params.size(); i++) { + final VariableElement p = params.get(i); + w.append(sep).append(p.asType().toString()).append(" ").append(p.getSimpleName()); + } + w.append(") { return new ").append(className).append("(false, ").append(inst); + for (int i = 1; i < params.size(); i++) { + final VariableElement p = params.get(i); + w.append(", ").append(p.getSimpleName()); + } + w.append("); }\n"); + w.append(" @Override protected void onError(Exception t) throws Throwable {\n"); + if (ol.onError().isEmpty()) { + w.append(" t.printStackTrace();"); + } else { + if (!findOnError(me, te, ol.onError(), isStatic)) { + return false; + } + if (isStatic) { + w.append(" ").append(te.getSimpleName()).append("."); + } else { + w.append(" $i."); + } + w.append(ol.onError()).append("(t"); + for (int i = 1; i < params.size(); i++) { + final VariableElement p = params.get(i); + w.append(", ").append(p.getSimpleName()); + } + w.append(");\n"); + } + w.append(" }\n"); + w.append(" @Override protected void onLocation(net.java.html.geo.Position p) throws Throwable {\n"); + if (isStatic) { + w.append(" ").append(te.getSimpleName()).append("."); + } else { + w.append(" $i."); + } + w.append(me.getSimpleName()).append("(p"); + for (int i = 1; i < params.size(); i++) { + final VariableElement p = params.get(i); + w.append(", ").append(p.getSimpleName()); + } + w.append(");\n"); + w.append(" }\n"); + w.append("}\n"); + w.close(); + } catch (IOException ex) { + Logger.getLogger(GeoProcessor.class.getName()).log(Level.SEVERE, null, ex); + error("Can't write handler class: " + ex.getMessage(), e); + return false; + } + + return true; + } + + private boolean findOnError(ExecutableElement errElem, TypeElement te, String name, boolean onlyStatic) { + String err = null; + METHODS: for (Element e : te.getEnclosedElements()) { + if (e.getKind() != ElementKind.METHOD) { + continue; + } + if (!e.getSimpleName().contentEquals(name)) { + continue; + } + if (onlyStatic && !e.getModifiers().contains(Modifier.STATIC)) { + errElem = (ExecutableElement) e; + err = "Would have to be static"; + continue; + } + ExecutableElement ee = (ExecutableElement) e; + TypeMirror excType = processingEnv.getElementUtils().getTypeElement(Exception.class.getName()).asType(); + final List<? extends VariableElement> params = ee.getParameters(); + if (params.size() < 1 || + !processingEnv.getTypeUtils().isAssignable(excType, ee.getParameters().get(0).asType()) + ) { + errElem = (ExecutableElement) e; + err = "Error method first argument needs to be Exception"; + continue; + } + final List<? extends Element> origParams = errElem.getParameters(); + if (params.size() != origParams.size()) { + errElem = (ExecutableElement) e; + err = "Error method must have the same parameters as @OnLocation one"; + continue; + } + for (int i = 1; i < origParams.size(); i++) { + final TypeMirror t1 = params.get(i).asType(); + final TypeMirror t2 = origParams.get(i).asType(); + if (!processingEnv.getTypeUtils().isSameType(t1, t2)) { + errElem = (ExecutableElement) e; + err = "Error method must have the same parameters as @OnLocation one"; + continue METHODS; + } + } + return true; + } + if (err == null) { + err = "Cannot find " + name + "(Exception) method in this class"; + } + error(err, errElem); + return false; + } +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/geo/src/main/java/org/netbeans/html/geo/impl/JsGLProvider.java ---------------------------------------------------------------------- diff --git a/geo/src/main/java/org/netbeans/html/geo/impl/JsGLProvider.java b/geo/src/main/java/org/netbeans/html/geo/impl/JsGLProvider.java new file mode 100644 index 0000000..f7578a8 --- /dev/null +++ b/geo/src/main/java/org/netbeans/html/geo/impl/JsGLProvider.java @@ -0,0 +1,154 @@ +/** + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package org.netbeans.html.geo.impl; + +import net.java.html.js.JavaScriptBody; +import org.netbeans.html.geo.spi.GLProvider; + +/** Implementation class to deal with browser's <code>navigator.geolocation</code> + * object. + * + * @author Jaroslav Tulach + */ +public final class JsGLProvider extends GLProvider<Object, Long> { + public JsGLProvider() { + } + + @JavaScriptBody(args = {}, body = "return !!navigator.geolocation;") + private static boolean hasGeolocation() { + return false; + } + + @JavaScriptBody( + args = { "c", "onlyOnce", "enableHighAccuracy", "timeout", "maximumAge" }, + javacall = true, + body = + "var self = this;\n" + + "var ok = function (position) {\n" + + " [email protected]::onLocation(Ljava/lang/Object;Ljava/lang/Object;)(c, position);\n" + + "};\n" + + "var fail = function (error) {\n" + + " [email protected]::onError(Ljava/lang/Object;Ljava/lang/String;I)(c, error.message, error.code);\n" + + "};\n" + + "var options = {};\n" + + "options.enableHighAccuracy = enableHighAccuracy;\n" + + "if (timeout >= 0) options.timeout = timeout;\n" + + "if (maximumAge >= 0) options.maximumAge = maximumAge;\n" + + "if (onlyOnce) {\n" + + " navigator.geolocation.getCurrentPosition(ok, fail, options);\n" + + " return 0;\n" + + "} else {\n" + + " return navigator.geolocation.watchPosition(ok, fail, options);\n" + + "}\n" + ) + private long doStart( + Query c, + boolean onlyOnce, + boolean enableHighAccuracy, + long timeout, + long maximumAge + ) { + return -1; + } + + protected void stop(long watch) { + } + + @Override + public Long start(Query c) { + if (!hasGeolocation()) { + return null; + } + return doStart(c, c.isOneTime(), c.isHighAccuracy(), c.getTimeout(), c.getMaximumAge()); + } + + final void onLocation(Object c, Object p) { + callback((Query)c, timeStamp(p), p, null); + } + + final void onError(Object c, final String msg, int code) { + final Exception err = new Exception(msg + " errno: " + code) { + @Override + public String getLocalizedMessage() { + return msg; + } + }; + callback((Query)c, 0L, null, err); + } + + @Override + @JavaScriptBody(args = {"watch"}, body = "navigator.geolocation.clearWatch(watch);") + public native void stop(Long watch); + + @JavaScriptBody(args = { "p" }, body = "return p.timestamp;") + private static native long timeStamp(Object position); + + @Override + @JavaScriptBody(args = { "coords" }, body = "return coords.coords.latitude;") + protected native double latitude(Object coords); + + @Override + @JavaScriptBody(args = { "coords" }, body = "return coords.coords.longitude;") + protected native double longitude(Object coords); + + @Override + @JavaScriptBody(args = { "coords" }, body = "return coords.coords.accuracy;") + protected native double accuracy(Object coords); + + @Override + @JavaScriptBody(args = {"coords"}, body = "return coords.coords.altitude ? coords.coords.altitude : null;") + protected native Double altitude(Object coords); + + @Override + @JavaScriptBody(args = {"coords"}, body = "return coords.coords.altitudeAccuracy ? coords.coords.altitudeAccuracy : null;") + protected native Double altitudeAccuracy(Object coords); + + @Override + @JavaScriptBody(args = {"coords"}, body = "return coords.coords.heading ? coords.coords.heading : null;") + protected native Double heading(Object coords); + + @Override + @JavaScriptBody(args = {"coords"}, body = "return coords.coords.speed ? coords.coords.speed : null;") + protected native Double speed(Object coords); + +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/geo/src/main/java/org/netbeans/html/geo/spi/CoordImpl.java ---------------------------------------------------------------------- diff --git a/geo/src/main/java/org/netbeans/html/geo/spi/CoordImpl.java b/geo/src/main/java/org/netbeans/html/geo/spi/CoordImpl.java new file mode 100644 index 0000000..b0f0a14 --- /dev/null +++ b/geo/src/main/java/org/netbeans/html/geo/spi/CoordImpl.java @@ -0,0 +1,87 @@ +/** + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package org.netbeans.html.geo.spi; + +import net.java.html.geo.Position; + +/** + * + * @author Jaroslav Tulach + */ +final class CoordImpl<Coords> extends Position.Coordinates { + private final Coords data; + private final GLProvider<Coords, ?> provider; + + CoordImpl(Coords data, GLProvider<Coords, ?> p) { + this.data = data; + this.provider = p; + } + + @Override public double getLatitude() { + return provider.latitude(data); + } + + @Override public double getLongitude() { + return provider.longitude(data); + } + + @Override public double getAccuracy() { + return provider.accuracy(data); + } + + @Override public Double getAltitude() { + return provider.altitude(data); + } + + @Override public Double getAltitudeAccuracy() { + return provider.altitudeAccuracy(data); + } + + @Override public Double getHeading() { + return provider.heading(data); + } + + @Override public Double getSpeed() { + return provider.speed(data); + } +} // end of CoordImpl http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/geo/src/main/java/org/netbeans/html/geo/spi/GLProvider.java ---------------------------------------------------------------------- diff --git a/geo/src/main/java/org/netbeans/html/geo/spi/GLProvider.java b/geo/src/main/java/org/netbeans/html/geo/spi/GLProvider.java new file mode 100644 index 0000000..6ea1346 --- /dev/null +++ b/geo/src/main/java/org/netbeans/html/geo/spi/GLProvider.java @@ -0,0 +1,306 @@ +/** + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package org.netbeans.html.geo.spi; + +import net.java.html.BrwsrCtx; +import net.java.html.geo.Position; +import net.java.html.geo.Position.Handle; +import net.java.html.geo.Position.Coordinates; +import org.netbeans.html.context.spi.Contexts.Builder; +import org.netbeans.html.geo.impl.Accessor; +import org.openide.util.lookup.ServiceProvider; + +/** SPI for those who wish to provide their own way of obtaining geolocation. + * Subclass this class, implement its method and register it into the system. + * You can either use {@link ServiceProvider} to register globally, or + * one can register into {@link BrwsrCtx} (via + * {@link Builder#register(java.lang.Class, java.lang.Object, int) context builder}). + * <p> + * There is default system provider (used as a fallback) based on + * <a href="http://www.w3.org/TR/geolocation-API/"> + * W3C's Geolocation</a> specification - if you are running inside a + * browser that supports such standard and you are satisfied with its + * behavior, you don't have to register anything. + * <p> + * The provider serves two purposes: + * <ol> + * <li> + * It handles a geolocation request and creates a "watch" to represent it - + * to do so implement the {@link #start(org.netbeans.html.geo.spi.GLProvider.Query) start} + * method and the {@link #stop(java.lang.Object) stop} method. + * </li> + * <li> + * Once the location is found, the provider needs to + * {@link #callback(org.netbeans.html.geo.spi.GLProvider.Query, long, java.lang.Object, java.lang.Exception) call back} + * with appropriate location information which can be extracted + * later via {@link #latitude(java.lang.Object)} {@link #longitude(java.lang.Object)}, and + * other methods in this that also need to be implemented. + * </li> + * </ol> + * <p> + * The provider is based on a + * <a href="http://wiki.apidesign.org/wiki/Singletonizer" target="_blank">singletonizer</a> + * pattern (applied twice) + * and as such one is only required to subclass just the {@link GLProvider} + * and otherwise has freedom choosing what classes to use + * to represent coordinates and watches. For example if it is enough to use + * an array for coordinates and a long number for a watch, one can do: + * <pre> + * <b>public final class</b> MyGeoProvider extends {@link GLProvider}<Double[], Long> { + * <em>// somehow implement the methods</em> + * } + * </pre> + * + * @author Jaroslav Tulach + * @param <Watch> your chosen type to represent one query (one time) or watch (repeated) request - + * this type is used in {@link #start(org.netbeans.html.geo.spi.GLProvider.Query) start} + * and {@link #stop(java.lang.Object) stop} methods. + * + * @param <Coords> your chosen type to represent geolocation coordinates - + * use in many methods in this class like {@link #latitude(java.lang.Object)} and + * {@link #longitude(java.lang.Object)}. + * + * @since 1.0 + */ +public abstract class GLProvider<Coords,Watch> { + static { + Accessor initChannel = new Accessor(false) { + @Override + public <Watch> Watch start(GLProvider<?, Watch> p, Accessor peer, boolean oneTime, boolean enableHighAccuracy, long timeout, long maximumAge) { + return p.start(new Query(peer, oneTime, enableHighAccuracy, timeout, maximumAge)); + } + + @Override + public <Watch> void stop(GLProvider<?, Watch> p, Watch w) { + p.stop(w); + } + + @Override + public void onError(Exception ex) { + throw new UnsupportedOperationException(); + } + + @Override + public void onLocation(Position position) { + throw new UnsupportedOperationException(); + } + }; + } + /** Start obtaining geolocation. + * When the client {@link Handle#start() requests location} (and + * your provider is found) this method should initialize the request or + * return <code>null</code> to give chance to another provider. + * + * @param c the query describing the request and + * to {@link #callback(org.netbeans.html.geo.spi.GLProvider.Query, long, java.lang.Object, java.lang.Exception) use when location is found} - + * keep it, you'll need it later + * + * @return an object representing the request (so it can be {@link #stop(java.lang.Object) stopped} later) + * or <code>null</code> if this provider was unable to start the request + */ + protected abstract Watch start(Query c); + + /** Called when a geolocation request should be stopped. + * + * @param watch the watch returned when {@link #start(org.netbeans.html.geo.spi.GLProvider.Query) starting} + * the request + */ + protected abstract void stop(Watch watch); + + /** Invoke this method when your provider obtained requested location. + * This single method is used for notification of success (when <code>ex</code> + * argument is <code>null</code> and <code>position</code> is provided) or + * a failure (when <code>ex</code> argument is non-<code>null</code>). + * A successful requests leads in a call to {@link Handle#onLocation(net.java.html.geo.Position)} + * while an error report leads to a call to {@link Handle#onError(java.lang.Exception)}. + * The actual call is sent to {@link BrwsrCtx#execute(java.lang.Runnable)} of + * context recorded when the {@link Query} was created to guarantee it + * happens on the right browser thread - however it may happen "later" + * when this method has already finished. + * + * @param c the query as provided when {@link #start(org.netbeans.html.geo.spi.GLProvider.Query) starting} + * the request + * @param timestamp milliseconds since epoch when the location has been obtained + * @param position your own, internal, representation of geolocation + * coordinates - will be passed back to other methods of this class + * like {@link #latitude(java.lang.Object)} and {@link #longitude(java.lang.Object)}. + * Can be <code>null</code> if <code>ex</code> is non-<code>null</code> + * @param ex an exception to signal an error - should be <code>null</code> + * when one notifies the successfully obtained <code>position</code> + */ + protected final void callback( + final Query c, + final long timestamp, final Coords position, + final Exception ex + ) { + c.ctx.execute(new Runnable() { + @Override + public void run() { + if (ex == null) { + c.peer.onLocation(new Position(timestamp, new CoordImpl<Coords>(position, GLProvider.this))); + } else { + c.peer.onError(ex); + } + } + }); + } + + /** Extracts value for {@link Coordinates#getLatitude()}. + * @param coords your own internal representation of coordinates. + * @return geographic coordinate specified in decimal degrees. + */ + protected abstract double latitude(Coords coords); + + /** Extracts value for {@link Coordinates#getLatitude()}. + * @param coords your own internal representation of coordinates. + * @return geographic coordinate specified in decimal degrees. + */ + protected abstract double longitude(Coords coords); + + /** Extracts value for {@link Coordinates#getLatitude()}. + * The accuracy attribute denotes the accuracy level of the latitude + * and longitude coordinates. + * + * @param coords your own internal representation of coordinates. + * @return accuracy in meters + */ + protected abstract double accuracy(Coords coords); + + /** Extracts value for {@link Coordinates#getAltitude()}. + * Denotes the height of the position, specified in meters above the ellipsoid. + * + * @param coords your own internal representation of coordinates. + * @return value in meters, may return null, if the information is not available + */ + protected abstract Double altitude(Coords coords); + + /** Extracts value for {@link Coordinates#getAltitudeAccuracy()} - + * the altitude accuracy is specified in meters. + * + * @param coords your own internal representation of coordinates. + * @return value in meters; may return null, if the information is not available + */ + protected abstract Double altitudeAccuracy(Coords coords); + + /** Extracts value for {@link Coordinates#getHeading()}. + * Denotes the magnitude of the horizontal component of the + * device's current velocity and is specified in meters per second. + * + * @param coords your own internal representation of coordinates. + * @return may return null, if the information is not available + */ + protected abstract Double heading(Coords coords); + + /** Extracts value for {@link Coordinates#getSpeed()}. + * Denotes the magnitude of the horizontal component of the + * device's current velocity and is specified in meters per second. + * + * @param coords your own internal representation of coordinates. + * @return may return null, if the information is not available + */ + protected abstract Double speed(Coords coords); + + /** Holds parameters describing the location query and is used by {@link GLProvider} to notify back + * results of its findings. + */ + public static final class Query { + private final boolean oneTime; + private final boolean enableHighAccuracy; + private final long timeout; + private final long maximumAge; + private final BrwsrCtx ctx; + final Accessor peer; + + Query(Accessor peer, boolean oneTime, boolean enableHighAccuracy, long timeout, long maximumAge) { + this.peer = peer; + this.oneTime = oneTime; + this.enableHighAccuracy = enableHighAccuracy; + this.timeout = timeout; + this.maximumAge = maximumAge; + ctx = BrwsrCtx.findDefault(Query.class); + } + + /** + * Is this one time or repeated request? Mimics value provided in + * {@link Handle constructor}. + * + * @return true if this is one time request, false if the request is + * permanent (up until {@link Handle#stop() } is called). + */ + public final boolean isOneTime() { + return oneTime; + } + + /** + * Turns on high accuracy mode as specified by the + * <a href="http://www.w3.org/TR/2012/PRÂgeolocationÂAPIÂ20120510/"> + * W3C's Geolocation API</a>. By default the mode is disabled. Mimics + * value of {@link Handle#setHighAccuracy(boolean)}. + * + * @return enable <code>true</code> or <code>false</code> + */ + public final boolean isHighAccuracy() { + return this.enableHighAccuracy; + } + + /** + * The amount of milliseconds to wait for a result. Mimics value of + * {@link Handle#setTimeout(long)}. + * + * @return time in milliseconds to wait for a result. + */ + public final long getTimeout() { + return this.timeout; + } + + /** + * Sets maximum age of cached results which are acceptable to be + * returned. Mimics value of {@link Handle#setMaximumAge(long)}. + * + * @return time in milliseconds of acceptable cached results + */ + public final long getMaximumAge() { + return this.maximumAge; + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/geo/src/main/java/org/netbeans/html/geo/spi/package.html ---------------------------------------------------------------------- diff --git a/geo/src/main/java/org/netbeans/html/geo/spi/package.html b/geo/src/main/java/org/netbeans/html/geo/spi/package.html new file mode 100644 index 0000000..6eb717c --- /dev/null +++ b/geo/src/main/java/org/netbeans/html/geo/spi/package.html @@ -0,0 +1,59 @@ +<!-- + + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + + Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + + Oracle and Java are registered trademarks of Oracle and/or its affiliates. + Other names may be trademarks of their respective owners. + + The contents of this file are subject to the terms of either the GNU + General Public License Version 2 only ("GPL") or the Common + Development and Distribution License("CDDL") (collectively, the + "License"). You may not use this file except in compliance with the + License. You can obtain a copy of the License at + http://www.netbeans.org/cddl-gplv2.html + or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + specific language governing permissions and limitations under the + License. When distributing the software, include this License Header + Notice in each file and include the License file at + nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + particular file as subject to the "Classpath" exception as provided + by Oracle in the GPL Version 2 section of the License file that + accompanied this code. If applicable, add the following below the + License Header, with the fields enclosed by brackets [] replaced by + your own identifying information: + "Portions Copyrighted [year] [name of copyright owner]" + + Contributor(s): + + The Original Software is NetBeans. The Initial Developer of the Original + Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + + If you wish your version of this file to be governed by only the CDDL + or only the GPL Version 2, indicate your decision by adding + "[Contributor] elects to include this software in this distribution + under the [CDDL or GPL Version 2] license." If you do not indicate a + single choice of license, a recipient has the option to distribute + your version of this file under either the CDDL, the GPL Version 2 or + to extend the choice of license to its licensees as provided above. + However, if you add GPL Version 2 code and therefore, elected the GPL + Version 2 license, then the option applies only if the new code is + made subject to such option by the copyright holder. + +--> +<!DOCTYPE html> +<html> + <head> + <title>Geolocation SPI</title> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <meta name="viewport" content="width=device-width"> + </head> + <body> + <div> + Service provider interfaces for those willing to + {@link org.netbeans.html.geo.spi.GLProvider provide their own way} + of obtaining proper geolocation. + </div> + </body> +</html> http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/geo/src/test/java/net/java/html/geo/OnLocationTest.java ---------------------------------------------------------------------- diff --git a/geo/src/test/java/net/java/html/geo/OnLocationTest.java b/geo/src/test/java/net/java/html/geo/OnLocationTest.java new file mode 100644 index 0000000..544d8c4 --- /dev/null +++ b/geo/src/test/java/net/java/html/geo/OnLocationTest.java @@ -0,0 +1,137 @@ +/** + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package net.java.html.geo; + +import org.testng.annotations.Test; +import static org.testng.Assert.*; + +/** Testing correctness of the generated code. + */ +public class OnLocationTest { + static int cnt; + static @OnLocation void onLocation(Position p) { + assertNotNull(p, "Position object provided"); + cnt++; + } + + @Test public void createOneTimeQueryStatic() { + net.java.html.geo.Position.Handle h = OnLocationHandle.createQuery(); + h.setHighAccuracy(false); + h.setTimeout(1000L); + h.setMaximumAge(1000L); + if (h.isSupported()) h.start(); + h.stop(); + } + + @Test public void onLocationHandleCallback() throws Throwable { + net.java.html.geo.Position.Handle h = OnLocationHandle.createQuery(); + cnt = 0; + h.onLocation(new Position(0L, null)); + assertEquals(cnt, 1, "The callback has been made"); + } + + @Test public void createRepeatableWatchStatic() { + net.java.html.geo.Position.Handle h = OnLocationHandle.createQuery(); + h.setHighAccuracy(false); + h.setTimeout(1000L); + h.setMaximumAge(1000L); + if (h.isSupported()) h.start(); + h.stop(); + } + + int instCnt; + Throwable instT; + @OnLocation(onError = "someError") void instance(Position p) throws Error { + assertNotNull(p, "Some position passed in"); + instCnt++; + } + void someError(Throwable t) throws Exception { + instT = t; + instCnt++; + } + + @Test public void createOneTimeQueryInstance() { + OnLocationTest t = new OnLocationTest(); + + net.java.html.geo.Position.Handle h = InstanceHandle.createQuery(t); + h.setHighAccuracy(false); + h.setTimeout(1000L); + h.setMaximumAge(1000L); + if (h.isSupported()) h.start(); + h.stop(); + } + + @Test public void onInstanceCallback() throws Throwable { + OnLocationTest t = new OnLocationTest(); + net.java.html.geo.Position.Handle h = InstanceHandle.createWatch(t); + h.onLocation(new Position(0L, null)); + assertEquals(t.instCnt, 1, "One callback made"); + } + + @Test public void onInstanceError() throws Throwable { + net.java.html.geo.Position.Handle h = InstanceHandle.createWatch(this); + InterruptedException e = new InterruptedException(); + h.onError(e); + assertEquals(instCnt, 1, "One callback made"); + assertEquals(instT, e, "The same exception passed in"); + } + + @Test public void createRepeatableWatch() { + OnLocationTest t = new OnLocationTest(); + + net.java.html.geo.Position.Handle h = InstanceHandle.createWatch(t); + h.setHighAccuracy(false); + h.setTimeout(1000L); + h.setMaximumAge(1000L); + if (h.isSupported()) h.start(); + h.stop(); + } + + @OnLocation(onError = "errParam") void withParam(Position pos, int param) { + instCnt = param; + } + + void errParam(Exception ex, int param) { + instCnt = param; + } +}
