+ This module was originally created to provide a way to handle + clicks on hyperlinks in the output window. Some more sophisticated + objects for describing intended operations can be added into this + module in the future. +
++ The URI-based actions are useful if the front-end and back-end of + the application is separated, e.g. in network environment. The + actions can be specified on back-end, but handled on front-end, + without any unnecessary communication. +
+ ++ API for invoking some intended operation, specified by + a URI. For example, for displaying a web page in browser, or for + opening a source file in editor. +
++ SPI for handlers that are able to invoke proper operation for + some URI. +
++ The code is checked by unit tests. +
++ Done. +
++ IntentManager.execute(Intent.forUri(new URI("scheme://path/"))); ++
+ @ServiceProvider(service = OpenUriHandler.class, position = 800) + public class TestOpenUriHandler implements OpenUriHandler { + + public boolean open(URI uri) { + if ("http".equals(uri.getScheme())) { + // open default browser + return true; + } else { + return false; + } + } + } ++
+ This module provides a contract between API clients that can express + some intention to invoke an operation (specified e.g. by a URI) and + SPI providers that can handle the URI. +
++ This is useful in client-server environments, where the intention + can be constructed on server-side, but handled on client-side. The + objects that describe the intention should be easy to construct, + transfer and interpret. +
++ No deprecation needed. +
++ Yes. +
++ No standards. +
++ No settings are read or written. +
++ 1.6 +
++ JRE +
++ No non-NB dependencies. +
++ Any platform. +
++ Standard module dependency is sufficient. +
++ Just module JAR. +
++ Yes. +
++ Only API and SPI packages are public. +
++ Installation location does not matter. +
++ No. +
++ No. +
++ No. +
++ No. +
++ No. +
++ No. +
++ No. +
++ No. +
++ The API is threadsafe. SPI implementations should ensure proper + synchronization. +
++ No clipboard access. +
++ No Drag & Drop support. +
++ No files are read or written by this module. +
+
+ The lookup is used to find registered OpenUriHandler
s.
+
+ No. +
++ No. +
++ No. +
++ No. +
++ No. +
++ Very little memory consumed. +
++ No. +
++ No. +
++ Code in the module is very simple. Performance is incluenced mosly + by SPI implementations, which should run quite quickly. +
++ No performance criteria are enforced. The plugged-in code is invoked + by a dedicated executor. +
++ No. +
++ No. +
++ No. +
++ No. +
++ No. +
++ No. +
++ No. +
++ No. +
++ No. +
++ * Result type of the operation will be a boolean value: true if the URI was + * handled, false if no provider was able to handle it. + *
+ * + * @param uri URI describing the operation. + * @return The new URI-based intended operation. + * + * @see OpenUriHandler + */ + public static Intent+ * This is a package-private implementation returned by + * {@link Intent#forUri(java.net.URI)}. + *
+ * + * @author jhavlin + */ +class UriIntent extends Intent+ * This is a handler for for intents created by + * {@link Intent#forUri(java.net.URI)}. + *
+ * + * @see Intent#forUri(java.net.URI) + * @author jhavlin + */ +public interface OpenUriHandler { + + /** + * Handle the passed URI, if it is supported by this handler. + * + *+ * To register a handler, use {@link ServiceProvider} annotation. Ensure + * that {@link ServiceProvider#position()} is set properly. + *
+ * + * @param uri The URI to open. + * + * @return True if the URI has been handled succesfully, false if this + * handler doesn't support it and thus it should be passed to next available + * handler. + * + * @see Intent#forUri(java.net.URI) + */ + boolean open(@NonNull URI uri); +} diff --git a/api.intent/test/unit/src/org/netbeans/api/intent/UriIntentTest.java b/api.intent/test/unit/src/org/netbeans/api/intent/UriIntentTest.java new file mode 100644 --- /dev/null +++ b/api.intent/test/unit/src/org/netbeans/api/intent/UriIntentTest.java @@ -0,0 +1,99 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 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]" + * + * 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. + * + * Contributor(s): + * + * Portions Copyrighted 2014 Sun Microsystems, Inc. + */ +package org.netbeans.api.intent; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import org.junit.Test; +import static org.junit.Assert.*; +import org.netbeans.junit.MockServices; +import org.netbeans.spi.intent.uri.OpenUriHandler; + +/** + * + * @author jhavlin + */ +public class UriIntentTest { + + @Test + public void testOpenUri() throws URISyntaxException, InterruptedException, + ExecutionException { + + Future extends Boolean> f = IntentManager.submit(Intent.forUri( + new URI("test://a/b/c/"))); + assertFalse(f.get()); + + MockServices.setServices(TestOpenUriHandler.class); + try { + assertFalse(TestOpenUriHandler.HANDLED); + Future extends Boolean> res2 = IntentManager.submit(Intent.forUri( + new URI("test://a/b/c/"))); + assertTrue(res2.get()); + assertTrue(TestOpenUriHandler.HANDLED); + + Future extends Boolean> res3 = IntentManager.submit(Intent.forUri( + new URI("other://x/y/z/"))); + assertFalse(res3.get()); + } finally { + MockServices.setServices(); + } + } + + @SuppressWarnings("PublicInnerClass") + public static class TestOpenUriHandler implements OpenUriHandler { + + @SuppressWarnings("PackageVisibleField") + static boolean HANDLED = false; + + @Override + public boolean open(URI uri) { + if ("test".equals(uri.getScheme())) { + HANDLED = true; + return true; + } else { + return false; + } + } + } +}