+ 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.
+
+ @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 OpenUriHandlers.
+
+
+
+
+
+
+
+
+ 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.
+
+
+
+
diff --git a/api.intent/build.xml b/api.intent/build.xml
new file mode 100644
--- /dev/null
+++ b/api.intent/build.xml
@@ -0,0 +1,5 @@
+
+
+ Builds, tests, and runs the project org.netbeans.api.intent
+
+
diff --git a/api.intent/manifest.mf b/api.intent/manifest.mf
new file mode 100644
--- /dev/null
+++ b/api.intent/manifest.mf
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+AutoUpdate-Show-In-Client: true
+OpenIDE-Module: org.netbeans.api.intent
+OpenIDE-Module-Localizing-Bundle: org/netbeans/api/intent/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
diff --git a/api.intent/nbproject/project.properties b/api.intent/nbproject/project.properties
new file mode 100644
--- /dev/null
+++ b/api.intent/nbproject/project.properties
@@ -0,0 +1,4 @@
+is.autoload=true
+javac.source=1.6
+javac.compilerargs=-Xlint -Xlint:-serial
+javadoc.arch=${basedir}/arch.xml
diff --git a/api.intent/nbproject/project.xml b/api.intent/nbproject/project.xml
new file mode 100644
--- /dev/null
+++ b/api.intent/nbproject/project.xml
@@ -0,0 +1,53 @@
+
+
+ org.netbeans.modules.apisupport.project
+
+
+ org.netbeans.api.intent
+
+
+ org.netbeans.api.annotations.common
+
+
+
+ 1
+ 1.25
+
+
+
+ org.openide.util.base
+
+
+
+ 9.1
+
+
+
+ org.openide.util.lookup
+
+
+
+ 8.26
+
+
+
+
+
+ unit
+
+ org.netbeans.libs.junit4
+
+
+
+ org.netbeans.modules.nbjunit
+
+
+
+
+
+ org.netbeans.api.intent
+ org.netbeans.spi.intent.uri
+
+
+
+
diff --git a/api.intent/src/org/netbeans/api/intent/Bundle.properties b/api.intent/src/org/netbeans/api/intent/Bundle.properties
new file mode 100644
--- /dev/null
+++ b/api.intent/src/org/netbeans/api/intent/Bundle.properties
@@ -0,0 +1,7 @@
+OpenIDE-Module-Display-Category=Infrastructure
+OpenIDE-Module-Long-Description=\
+ API for invoking intended operations (described by suitable type of object, e.g. \
+ URI) by some of registered handlers.\n\
+ SPI for handlers of possible intended operations.
+OpenIDE-Module-Name=Intent API
+OpenIDE-Module-Short-Description=Performing intended operations by suitable handlers
diff --git a/api.intent/src/org/netbeans/api/intent/Intent.java b/api.intent/src/org/netbeans/api/intent/Intent.java
new file mode 100644
--- /dev/null
+++ b/api.intent/src/org/netbeans/api/intent/Intent.java
@@ -0,0 +1,80 @@
+/*
+ * 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 org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.spi.intent.uri.OpenUriHandler;
+import org.openide.util.Parameters;
+
+/**
+ * Class that describes an intended operation.
+ *
+ * @author jhavlin
+ *
+ * @param Result type of the intended operation.
+ * @see IntentManager
+ */
+public abstract class Intent {
+
+ abstract R invoke();
+
+ Intent() {
+ }
+
+ /**
+ * Create an intended operation described by a URI.
+ *
+ * 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 forUri(@NonNull URI uri) {
+ Parameters.notNull("uri", uri); //NOI18N
+ return new UriIntent(uri);
+ }
+}
diff --git a/api.intent/src/org/netbeans/api/intent/IntentManager.java b/api.intent/src/org/netbeans/api/intent/IntentManager.java
new file mode 100644
--- /dev/null
+++ b/api.intent/src/org/netbeans/api/intent/IntentManager.java
@@ -0,0 +1,95 @@
+/*
+ * 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.util.concurrent.Callable;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Future;
+import org.openide.util.RequestProcessor;
+
+/**
+ * Manager for execution and submitting of {@link Intent}s.
+ *
+ * @author jhavlin
+ * @see Executor
+ */
+public final class IntentManager {
+
+ private static final RequestProcessor RP = new RequestProcessor(
+ IntentManager.class);
+
+ private IntentManager() {
+ }
+
+ /**
+ * Execute an intent by an internal executor.
+ *
+ * @param intent The intent to execute.
+ */
+ public static void execute(final Intent> intent) {
+ RP.execute(new Runnable() {
+
+ @Override
+ public void run() {
+ intent.invoke();
+ }
+ });
+ }
+
+ /**
+ * Submit an intent to an internal executor.
+ *
+ * @param Result type of the intended operation.
+ * @param intent The intent to submit.
+ *
+ * @return {@link Future} object of the submitted task.
+ */
+ public static Future extends T> submit(final Intent intent) {
+ return RP.submit(new Callable() {
+
+ @Override
+ public T call() throws Exception {
+ return intent.invoke();
+ }
+ });
+ }
+}
diff --git a/api.intent/src/org/netbeans/api/intent/UriIntent.java b/api.intent/src/org/netbeans/api/intent/UriIntent.java
new file mode 100644
--- /dev/null
+++ b/api.intent/src/org/netbeans/api/intent/UriIntent.java
@@ -0,0 +1,76 @@
+/*
+ * 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 org.netbeans.spi.intent.uri.OpenUriHandler;
+import org.openide.util.Lookup;
+
+/**
+ * Intent described by a URI object.
+ *
+ *
+ * This is a package-private implementation returned by
+ * {@link Intent#forUri(java.net.URI)}.
+ *
+ *
+ * @author jhavlin
+ */
+class UriIntent extends Intent {
+
+ private final URI uri;
+
+ UriIntent(URI uri) {
+ this.uri = uri;
+ }
+
+ @Override
+ Boolean invoke() {
+ for (OpenUriHandler handler : Lookup.getDefault().lookupAll(
+ OpenUriHandler.class)) {
+ if (handler.open(uri)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/api.intent/src/org/netbeans/spi/intent/uri/OpenUriHandler.java b/api.intent/src/org/netbeans/spi/intent/uri/OpenUriHandler.java
new file mode 100644
--- /dev/null
+++ b/api.intent/src/org/netbeans/spi/intent/uri/OpenUriHandler.java
@@ -0,0 +1,80 @@
+/*
+ * 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.spi.intent.uri;
+
+import java.net.URI;
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.api.intent.Intent;
+import org.openide.util.lookup.ServiceProvider;
+
+/**
+ * SPI for handlers that can process URI hyperlinks that were clicked in the
+ * application (or somehow invoked).
+ *
+ *
+ * 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;
+ }
+ }
+ }
+}
diff --git a/api.io/arch.xml b/api.io/arch.xml
new file mode 100644
--- /dev/null
+++ b/api.io/arch.xml
@@ -0,0 +1,1188 @@
+
+
+]>
+
+
+
+
+ &api-questions;
+
+
+
+
+
+
+ The module contains APIs for creating output panes (e.g. output tabs in Output Window in the IDE)
+ and for writing data into them. It also supports some advanced techniques, e.g. color text,
+ hyperlinks, code folding, scrolling to stored positions.
+
+
+
+
+ SPI for providing custom implementations of output window is also included in this module, in package
+ org.netbeans.spi.io
+
+
+
+
+
+
+
+
+
+ Unit test will be prepared for invocable code in API classes. But most of the
+ code is just definition of API and SPI.
+
+
+
+
+
+
+
+
+ The design, implementation, preparing unit tests and reviews will
+ probably take several weeks.
+
+
+
+
+
+
+
+
+
+
+ The basic use-case is printing a simple text, e.g. text output of an application,
+ into a dedicated pane in the UI, e.g. a tab in Output Window in the IDE.
+
+
+ InputOutput io = InputOutput.get("UseCase1", true);
+ io.getOut().println("This is a simple output");
+ io.getOut().close();
+
+
+
+
+
+ Implementations can support hyperlinks. If the hyperlink is defined by a URI,
+ it will be opened by the UI part of the application when the hyperlink is clicked
+ in the output window. The following example will open a file and place the cursor
+ at line and column specified by query part of the URI (after question mark).
+
+
+ InputOutput io = InputOutput.get("UseCase2", false);
+ io.getOut().print("A line containing a ");
+ io.getOut().print("hyperlink", Hyperlink.forURI(new URI("file://n:/test/Test.java?line=4&col=2")));
+ io.getOut().println(" for a URI.");
+ io.getOut().close();
+
+
+
+
+
+ Hyperlinks can be also used to invoke some code when clicked.
+
+
+ InputOutput io = InputOutput.get("UseCase3", true);
+ io.getOut().print("A line containing a ");
+ io.getOut().print("hyperlink", Hyperlink.onClick(new Runnable() {
+ public void run() {
+ System.gc();
+ }
+ }));
+ io.getOut().println(" for invocation of custom code.");
+ io.getOut().close();
+
+
+
+
+
+ Print a color text. Users can select a predefined color for
+ common cases (debug, warning, failure, success), or custom
+ color specified as RGB value.
+
+
+ InputOutput io = InputOutput.get("UseCase4", true);
+ io.getOut().println("Let's print some info", OutputColor.debug());
+ io.getOut().println("or warning with appropriate color", OutputColor.warning());
+ io.getOut().println("Maybe also text with custom reddish color", OutputColor.rgb(255, 16, 16));
+ io.getOut().close();
+
+
+
+
+
+ It is possible to reuse already created output pane and clear
+ all the previously printed text if it is not needed any more.
+
+
+ InputOutput io = InputOutput.get("UseCase5", true);
+ io.getOut().println("Let's print some text");
+ io.getErr().println("and reset the pane immediately.");
+ io.reset();
+ io.getOut().println("The pane is now empty and we can reuse it simply");
+ io.getOut().close();
+
+
+
+
+
+
+
+
+
+
+ The Input/Output API and SPI is a small module
+ which contains InputOutput and related interfaces used in
+ driving the Output Window.
+
+
+ The normal implementation is org.netbeans.core.output2.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Backward compatibility of other modules is not broken.
+
+
+ This module should replace original I/O API module
+ org.openide.io, which has the same goals, but which is
+ not UI independent, and which is difficult to extend.
+
+
+
+
+
+
+
+
+ Yes. There is not much to internationalize.
+
+
+
+
+
+
+
+
+ The module defines an API.
+
+
+
+
+
+
+
+
+ N/A. No settings are read or written by this module.
+
+ Availability of some implementation of the SPI is guaranteed by
+ "OpenIDE-Module-Needs: org.netbeans.spi.io.InputOutputProvider" in
+ the manifest of this module.
+
+
+
+
+
+
+
+
+ Just the module JAR.
+
+
+
+
+
+
+
+
+ Yes.
+
+
+
+
+
+
+
+
+ No; only API classes are public.
+
+
+
+
+
+
+
+
+ Anywhere.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ API classes are thread safe, they mostly represent immutable
+ objects, or delegate to the SPI.
+
+
+ Implementators of the SPI should ensure that their code is properly
+ synchronized, as it can be called from any thread.
+
+
+
+
+
+
+
+
+ Plain Unicode text only.
+
+
+
+
+
+
+
+
+ N/A
+
+
+
+
+
+
+
+
+ None.
+
+
+
+
+
+
+
+
+ IOProvider.getDefault() asks lookup for the first instance
+ of InputOutputProvider. This is normally provided by
+ org.netbeans.core.output2.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ N/A
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ Scalability in GUI speed and memory consumption is probably limited
+ only by the Output Window implementation.
+
+
+
+
+
+
+
+
+ No special behavior.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ No, but the implementation may.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
diff --git a/api.io/build.xml b/api.io/build.xml
new file mode 100644
--- /dev/null
+++ b/api.io/build.xml
@@ -0,0 +1,5 @@
+
+
+ Builds, tests, and runs the project org.netbeans.api.io
+
+
diff --git a/api.io/manifest.mf b/api.io/manifest.mf
new file mode 100644
--- /dev/null
+++ b/api.io/manifest.mf
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+AutoUpdate-Show-In-Client: true
+OpenIDE-Module: org.netbeans.api.io
+OpenIDE-Module-Localizing-Bundle: org/netbeans/api/io/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+OpenIDE-Module-Needs: org.netbeans.spi.io.InputOutputProvider
diff --git a/api.io/nbproject/project.properties b/api.io/nbproject/project.properties
new file mode 100644
--- /dev/null
+++ b/api.io/nbproject/project.properties
@@ -0,0 +1,4 @@
+is.autoload=true
+javac.source=1.6
+javac.compilerargs=-Xlint -Xlint:-serial
+javadoc.arch=${basedir}/arch.xml
diff --git a/api.io/nbproject/project.xml b/api.io/nbproject/project.xml
new file mode 100644
--- /dev/null
+++ b/api.io/nbproject/project.xml
@@ -0,0 +1,54 @@
+
+
+ org.netbeans.modules.apisupport.project
+
+
+ org.netbeans.api.io
+
+
+ org.netbeans.api.annotations.common
+
+
+
+ 1
+ 1.25
+
+
+
+ org.openide.util.base
+
+
+
+ 9.1
+
+
+
+ org.openide.util.lookup
+
+
+
+ 8.26
+
+
+
+
+
+ unit
+
+ org.netbeans.libs.junit4
+
+
+
+ org.netbeans.modules.nbjunit
+
+
+
+
+
+ org.netbeans.api.io
+ org.netbeans.spi.io
+ org.netbeans.spi.io.support
+
+
+
+
diff --git a/api.io/src/org/netbeans/api/io/Bundle.properties b/api.io/src/org/netbeans/api/io/Bundle.properties
new file mode 100644
--- /dev/null
+++ b/api.io/src/org/netbeans/api/io/Bundle.properties
@@ -0,0 +1,6 @@
+OpenIDE-Module-Display-Category=Infrastructure
+OpenIDE-Module-Long-Description=\
+ API classes for creating output panes (e.g. tabs in output window) and for writing data into them.\n\
+ SPI for custom implementations of output window.
+OpenIDE-Module-Name=I/O API and SPI
+OpenIDE-Module-Short-Description=APIs and SPIs related to displaying output.
diff --git a/api.io/src/org/netbeans/api/io/Fold.java b/api.io/src/org/netbeans/api/io/Fold.java
new file mode 100644
--- /dev/null
+++ b/api.io/src/org/netbeans/api/io/Fold.java
@@ -0,0 +1,131 @@
+/*
+ * 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.io;
+
+import java.io.PrintWriter;
+import org.netbeans.spi.io.InputOutputProvider;
+
+/**
+ * A fold (nested or standalone) in the output window.
+ *
+ *
+ * Methods of this class can be called in any thread.
+ *
+ *
+ * @author jhavlin
+ */
+public abstract class Fold {
+
+ static final Fold UNSUPPORTED = new Fold() {
+
+ @Override
+ public void setExpanded(boolean expanded) {
+ }
+
+ @Override
+ void endFold() {
+ }
+ };
+
+ private Fold() {
+ }
+
+ static Fold create(
+ InputOutputProvider provider, IO io, OW writer,
+ F fold) {
+ if (fold == null) {
+ return UNSUPPORTED;
+ } else {
+ return new Impl(provider, io, writer, fold);
+ }
+ }
+
+ /**
+ * Set fold expansion state.
+ *
+ * @param expanded True to expand the fold, false to collapse it.
+ */
+ public abstract void setExpanded(boolean expanded);
+
+ abstract void endFold();
+
+ /**
+ * Expand the fold.
+ */
+ public final void expand() {
+ setExpanded(true);
+ }
+
+ /**
+ * Collapse the fold.
+ */
+ public final void collapse() {
+ setExpanded(false);
+ }
+
+ private static class Impl extends Fold {
+
+ private final InputOutputProvider provider;
+ private final IO io;
+ private final OW writer;
+ private final F fold;
+
+ public Impl(InputOutputProvider provider, IO io,
+ OW writer, F fold) {
+
+ this.provider = provider;
+ this.io = io;
+ this.writer = writer;
+ this.fold = fold;
+ }
+
+ @Override
+ public void setExpanded(boolean expanded) {
+ provider.setFoldExpanded(io, writer, fold, expanded);
+ }
+
+ @Override
+ void endFold() {
+ provider.endFold(io, writer, fold);
+ }
+ }
+}
diff --git a/api.io/src/org/netbeans/api/io/Hyperlink.java b/api.io/src/org/netbeans/api/io/Hyperlink.java
new file mode 100644
--- /dev/null
+++ b/api.io/src/org/netbeans/api/io/Hyperlink.java
@@ -0,0 +1,159 @@
+/*
+ * 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.io;
+
+import java.net.URI;
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.modules.io.HyperlinkAccessor;
+import org.openide.util.Parameters;
+
+/**
+ * Hyperlink in output window. It can be specified by a URI to open (e.g. file +
+ * row + col), or a {@link Runnable} to invoke when the hyperlink is clicked.
+ *
+ * @author jhavlin
+ */
+public abstract class Hyperlink {
+
+ private final boolean important;
+
+ private Hyperlink(boolean important) {
+ this.important = important;
+ }
+
+ static {
+ HyperlinkAccessor.setDefault(new HyperlinkAccessorImpl());
+ }
+
+ /**
+ * @return True if the hyperlink has been marked as important, false if it
+ * is a standard link.
+ */
+ boolean isImportant() {
+ return important;
+ }
+
+ /**
+ * Create a new hyperlink for specified URI.
+ *
+ * @param uri Hyperlink targed.
+ *
+ * @return The new hyperlink.
+ */
+ @NonNull
+ public static Hyperlink from(@NonNull URI uri) {
+ return Hyperlink.from(uri, false);
+ }
+
+ /**
+ * Create a new hyperlink for specified {@link Runnable}, which will be
+ * invoked when the line is clicked.
+ *
+ * @param runnable The runnable to run on click.
+ * @return The new hyperlink.
+ */
+ @NonNull
+ public static Hyperlink from(@NonNull Runnable runnable) {
+ return from(runnable, false);
+ }
+
+ /**
+ * Create a new hyperlink for specified URI.
+ *
+ * @param uri Hyperlink targed.
+ * @param important True if the hyperlink should be handled as an important
+ * one, false if it is a standard one.
+ *
+ * @return The new hyperlink.
+ */
+ @NonNull
+ public static Hyperlink from(@NonNull URI uri, boolean important) {
+ Parameters.notNull("uri", uri);
+ return new UriHyperlink(uri, important);
+ }
+
+ /**
+ * Create a new hyperlink for specified {@link Runnable}, which will be
+ * invoked when the line is clicked.
+ *
+ * @param runnable The runnable to run on click.
+ * @param important True if the hyperlink should be handled as an important
+ * one, false if it is a standard one.
+ * @return The new hyperlink.
+ */
+ @NonNull
+ public static Hyperlink from(@NonNull Runnable runnable,
+ boolean important) {
+ Parameters.notNull("runnable", runnable);
+ return new OnClickHyperlink(runnable, important);
+ }
+
+ @SuppressWarnings("PackageVisibleInnerClass")
+ static class OnClickHyperlink extends Hyperlink {
+
+ private final Runnable runnable;
+
+ public OnClickHyperlink(Runnable runnable, boolean important) {
+ super(important);
+ this.runnable = runnable;
+ }
+
+ public Runnable getRunnable() {
+ return runnable;
+ }
+ }
+
+ @SuppressWarnings("PackageVisibleInnerClass")
+ static class UriHyperlink extends Hyperlink {
+
+ private final URI uri;
+
+ public UriHyperlink(URI uri, boolean important) {
+ super(important);
+ this.uri = uri;
+ }
+
+ public URI getUri() {
+ return uri;
+ }
+ }
+}
diff --git a/api.io/src/org/netbeans/api/io/HyperlinkAccessorImpl.java b/api.io/src/org/netbeans/api/io/HyperlinkAccessorImpl.java
new file mode 100644
--- /dev/null
+++ b/api.io/src/org/netbeans/api/io/HyperlinkAccessorImpl.java
@@ -0,0 +1,89 @@
+/*
+ * 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.io;
+
+import java.net.URI;
+import org.netbeans.modules.io.HyperlinkAccessor;
+import org.netbeans.spi.io.support.HyperlinkType;
+
+/**
+ * Implementation of accessor that enables retrieving information about
+ * hyperlinks in SPI.
+ *
+ * @author jhavlin
+ */
+class HyperlinkAccessorImpl extends HyperlinkAccessor {
+
+ @Override
+ public HyperlinkType getType(Hyperlink hyperlink) {
+ if (hyperlink instanceof Hyperlink.OnClickHyperlink) {
+ return HyperlinkType.FROM_RUNNABLE;
+ } else if (hyperlink instanceof Hyperlink.UriHyperlink) {
+ return HyperlinkType.FROM_URI;
+ } else {
+ throw new IllegalArgumentException("Unknown hyperlink."); //NOI18N
+ }
+ }
+
+ @Override
+ public boolean isImportant(Hyperlink hyperlink) {
+ return hyperlink.isImportant();
+ }
+
+ @Override
+ public Runnable getRunnable(Hyperlink hyperlink) {
+ if (hyperlink instanceof Hyperlink.OnClickHyperlink) {
+ return ((Hyperlink.OnClickHyperlink) hyperlink).getRunnable();
+ } else {
+ throw new IllegalArgumentException("Not an ON_CLICK link.");//NOI18N
+ }
+ }
+
+ @Override
+ public URI getURI(Hyperlink hyperlink) {
+ if (hyperlink instanceof Hyperlink.UriHyperlink) {
+ return ((Hyperlink.UriHyperlink) hyperlink).getUri();
+ } else {
+ throw new IllegalArgumentException("Not a FOR_URI link."); //NOI18N
+ }
+ }
+}
diff --git a/api.io/src/org/netbeans/api/io/IOProvider.java b/api.io/src/org/netbeans/api/io/IOProvider.java
new file mode 100644
--- /dev/null
+++ b/api.io/src/org/netbeans/api/io/IOProvider.java
@@ -0,0 +1,296 @@
+/*
+ * 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.io;
+
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.util.Collection;
+import java.util.Set;
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.spi.io.InputOutputProvider;
+import org.openide.util.Lookup;
+import org.openide.util.Parameters;
+
+/**
+ * A factory for IO tabs shown in the output window. To create a new tab to
+ * write to, call e.g.
+ * IOProvider.getDefault().getIO("MyTab", false) (pass true if
+ * there may be an existing tab with the same name and you want to write to a
+ * new tab).
+ *
+ *
+ * Methods of this class can be called in any thread.
+ *
+ *
+ * @author Jesse Glick, Jaroslav Havlin
+ */
+public abstract class IOProvider {
+
+ private IOProvider() {
+ }
+
+ /**
+ * Get the default I/O provider.
+ *
+ * Normally this is taken from {@link Lookup#getDefault} but if there is no
+ * instance in lookup, a fallback instance is created which just uses the
+ * standard system I/O streams. This is useful for unit tests and perhaps
+ * for standalone usage of various libraries.
+ *
+ *
+ * @return The default instance (never null).
+ */
+ @NonNull
+ public static IOProvider getDefault() {
+ InputOutputProvider, ?, ?, ?> def
+ = Lookup.getDefault().lookup(InputOutputProvider.class);
+ if (def != null) {
+ return wrapProvider(def);
+ } else {
+ return wrapProvider(new Trivial());
+ }
+ }
+
+ private static IOProvider wrapProvider(
+ InputOutputProvider provider) {
+
+ return new Impl(provider);
+ }
+
+ /**
+ * Gets IOProvider of selected name or delegates to getDefault() if none was
+ * found.
+ *
+ * @param id ID of provider.
+ * @return The instance corresponding to provided name or default instance
+ * if not found.
+ */
+ @NonNull
+ public static IOProvider get(@NonNull String id) {
+ Parameters.notNull("id", id);
+
+ @SuppressWarnings("rawtypes")
+ Collection extends InputOutputProvider> providers
+ = Lookup.getDefault().lookupAll(InputOutputProvider.class);
+
+ for (InputOutputProvider, ?, ?, ?> p : providers) {
+ if (p.getId().equals(id)) {
+ return wrapProvider(p);
+ }
+ }
+ return getDefault();
+ }
+
+ /**
+ * Gets identifier of this provider.
+ *
+ * @return Name of this provider.
+ */
+ @NonNull
+ public abstract String getId();
+
+ /**
+ * Get a named instance of InputOutput, which represents an output tab in
+ * the output window. Streams for reading/writing can be accessed via
+ * getters on the returned instance.
+ *
+ * @param name A localised display name for the tab.
+ * @param newIO If true, a new InputOutput is
+ * returned, else an existing InputOutput of the same name may
+ * be returned.
+ * @return An InputOutput instance for accessing the new tab.
+ * @see InputOutput
+ */
+ @NonNull
+ public abstract InputOutput getIO(@NonNull String name, boolean newIO);
+
+ /**
+ * Get a named instance of InputOutput, which represents an output tab in
+ * the output window. Streams for reading/writing can be accessed via
+ * getters on the returned instance.
+ *
+ * @param name A localised display name for the tab.
+ * @param newIO If true, a new InputOutput is
+ * returned, else an existing InputOutput of the same name may
+ * be returned.
+ * @param lookup Lookup which may contain additional information for various
+ * implementations of output window.
+ * @return An InputOutput instance for accessing the new tab.
+ * @see InputOutput
+ */
+ @NonNull
+ public abstract InputOutput getIO(@NonNull String name, boolean newIO,
+ @NonNull Lookup lookup);
+
+ /**
+ * Implementation of IOProvider that uses {@link InputOutputProvider} SPI
+ * internally.
+ *
+ * @param
+ * @param
+ * @param
+ */
+ private static class Impl
+ extends IOProvider {
+
+ private final InputOutputProvider impl;
+
+ public Impl(InputOutputProvider impl) {
+ this.impl = impl;
+ }
+
+ @Override
+ public String getId() {
+ return impl.getId();
+ }
+
+ @Override
+ public InputOutput getIO(String name, boolean newIO) {
+ return getIO(name, newIO, Lookup.EMPTY);
+ }
+
+ @Override
+ public InputOutput getIO(String name, boolean newIO, Lookup lookup) {
+ Parameters.notNull("name", name);
+ Parameters.notNull("lookup", lookup);
+ return InputOutput.create(impl, impl.getIO(name, newIO, lookup));
+ }
+ }
+
+ /**
+ * Trivial implementation of {@link IOProvider} that uses system input,
+ * output and error streams.
+ */
+ private static class Trivial
+ implements InputOutputProvider