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,1172 @@
+
+
+]>
+
+
+
+
+ &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();
+
+
+
+
+
+ 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.from(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.
+
+
+
+
+
+
+
+ 1.7
+
+
+
+
+
+
+ JRE
+
+
+
+
+
+
+
+
+
+
+
+
+
+ None.
+
+
+
+
+
+
+ Any.
+
+
+
+
+
+
+
+ Normal module dependency is enough.
+
+
+ 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.
+
+
+
+
+
+
+
+
+ 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,116 @@
+/*
+ * 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 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 {@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 {@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 {@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;
+ }
+ }
+}
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,77 @@
+/*
+ * 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 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 {
+ 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
+ }
+ }
+}
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 {
+
+ @Override
+ public String getId() {
+ return "Trivial";
+ }
+
+ @Override
+ public Object getIO(String name, boolean newIO, Lookup lookup) {
+ return this;
+ }
+
+ @Override
+ public Reader getIn(Object io) {
+ return new InputStreamReader(System.in);
+ }
+
+ @Override
+ public PrintWriter getOut(Object io) {
+ return new PrintWriter(System.out);
+ }
+
+ @Override
+ public PrintWriter getErr(Object io) {
+ return new PrintWriter(System.err);
+ }
+
+ @Override
+ public void print(Object io, PrintWriter writer, String text,
+ Hyperlink link, OutputColor color, boolean printLineEnd) {
+ writer.print(text);
+ if (printLineEnd) {
+ writer.println();
+ }
+ }
+
+ @Override
+ public Lookup getIOLookup(Object io) {
+ return Lookup.EMPTY;
+ }
+
+ @Override
+ public void resetIO(Object io) {
+ }
+
+ @Override
+ public void showIO(Object io,
+ Set operations) {
+ }
+
+ @Override
+ public void closeIO(Object io) {
+ }
+
+ @Override
+ public boolean isIOClosed(Object io) {
+ return false;
+ }
+
+ @Override
+ public Void getCurrentPosition(Object io, PrintWriter writer) {
+ return null;
+ }
+
+ @Override
+ public void scrollTo(Object io, PrintWriter writer, Void position) {
+ }
+
+ @Override
+ public Void startFold(Object io, PrintWriter writer, boolean expanded) {
+ return null;
+ }
+
+ @Override
+ public void endFold(Object io, PrintWriter writer, Void fold) {
+ }
+
+ @Override
+ public void setFoldExpanded(Object io, PrintWriter writer, Void fold,
+ boolean expanded) {
+ }
+
+ @Override
+ public String getIODescription(Object io) {
+ return null;
+ }
+
+ @Override
+ public void setIODescription(Object io, String description) {
+ }
+ }
+}
diff --git a/api.io/src/org/netbeans/api/io/InputOutput.java b/api.io/src/org/netbeans/api/io/InputOutput.java
new file mode 100644
--- /dev/null
+++ b/api.io/src/org/netbeans/api/io/InputOutput.java
@@ -0,0 +1,314 @@
+/*
+ * 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 java.io.Reader;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+import org.netbeans.api.annotations.common.CheckForNull;
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.api.annotations.common.NullAllowed;
+import org.netbeans.spi.io.InputOutputProvider;
+import org.openide.util.Lookup;
+
+/**
+ * An I/O connection to one tab on the Output Window. To acquire an instance to
+ * write to, call, e.g.,
+ * IOProvider.getDefault().getInputOutput("someName", false)
. To
+ * get actual streams to write to, call getOut()
or
+ * getErr()
on the returned instance.
+ *
+ * Generally it is preferable not to hold a reference to an instance of
+ * {@link org.netbeans.api.io.InputOutput}, but rather to fetch it by name from
+ * {@link org.netbeans.api.io.IOProvider} as needed.
+ *
+ *
+ *
+ * Methods of this class can be called in any thread.
+ *
+ *
+ * @see OutputWriter
+ * @author Ian Formanek, Jaroslav Tulach, Petr Hamernik, Ales Novak, Jan
+ * Jancura, Jaroslav Havlin
+ */
+public abstract class InputOutput implements Lookup.Provider {
+
+ private static final Set DEFAULT_SHOW_OPERATIONS
+ = EnumSet.of(ShowOperation.OPEN, ShowOperation.MAKE_VISIBLE);
+
+ private InputOutput() {
+ }
+
+ /**
+ * Get a named instance of InputOutput from the default {@link IOProvider},
+ * which represents an output tab in the output window. Streams for
+ * reading/writing can be accessed via getters on the returned instance.
+ *
+ *
+ * This is a shorthand for {@code IOProvider.getDefault().getIO(...)}.
+ *
+ *
+ * @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 IOProvider
+ */
+ @NonNull
+ public static InputOutput get(@NonNull String name, boolean newIO) {
+ return IOProvider.getDefault().getIO(name, newIO);
+ }
+
+ /**
+ * Get a named instance of InputOutput from the default {@link IOProvider},
+ * which represents an output tab in the output window. Streams for
+ * reading/writing can be accessed via getters on the returned instance.
+ *
+ *
+ * This is a shorthand for {@code IOProvider.getDefault().getIO(...)}.
+ *
+ *
+ * @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 IOProvider
+ */
+ @NonNull
+ public static InputOutput get(@NonNull String name, boolean newIO,
+ @NonNull Lookup lookup) {
+ return IOProvider.getDefault().getIO(name, newIO, lookup);
+ }
+
+ /**
+ * Get a reader to read from the tab.
+ *
+ * @return The reader.
+ */
+ @NonNull
+ public abstract Reader getIn();
+
+ /**
+ * Acquire an output writer to write to the tab.
+ *
+ * @return The writer.
+ */
+ @NonNull
+ public abstract OutputWriter getOut();
+
+ /**
+ * Get an output writer to write to the tab in error mode. This might show
+ * up in a different color than the regular output, e.g., or appear in a
+ * separate pane.
+ *
+ * @return The writer.
+ */
+ @NonNull
+ public abstract OutputWriter getErr();
+
+ /**
+ * Clear the output pane.
+ */
+ public abstract void reset();
+
+ /**
+ * Get lookup which may contain extensions provided by implementation of
+ * output window.
+ *
+ * @return The lookup.
+ */
+ @NonNull
+ @Override
+ public abstract Lookup getLookup();
+
+ /**
+ * Closes this tab. The effect of calling any method on an instance of
+ * InputOutput after calling close()
on it is
+ * undefined.
+ */
+ public abstract void close();
+
+ /**
+ * Test whether this tab has been closed, either by a call to
+ * {@link #close()} or by the user closing the tab in the UI.
+ *
+ * @return Value true
if it is closed.
+ */
+ public abstract boolean isClosed();
+
+ /**
+ * Get description of this I/O instance.
+ *
+ * @return The description, or null if not set.
+ */
+ @CheckForNull
+ public abstract String getDescription();
+
+ /**
+ * Set description of this I/O instance. It can be used e.g. as tooltip for
+ * output tab in the GUI.
+ *
+ * @param description The description, can be null.
+ */
+ public abstract void setDescription(@NullAllowed String description);
+
+ static InputOutput create(
+ InputOutputProvider provider, IO io) {
+
+ return new Impl(provider, io);
+ }
+
+ /**
+ * Show this I/O if possible (e.g. in tabbed pane).
+ *
+ * Calling this method is the same as calling:
+ *
+ *
+ * show(EnumSet.of(ShowOperation.OPEN, ShowOperation.MAKE_VISIBLE));
+ *
+ *
+ * @see #show(java.util.Set)
+ */
+ public final void show() {
+ show(DEFAULT_SHOW_OPERATIONS);
+ }
+
+ /**
+ * Show this I/O if possible (e.g. in tabbed pane).
+ *
+ * @param operations Set of operations that should be invoked to show the
+ * output. If the set is empty or null, pane for this I/O will be only
+ * selected, but its component will not be opened or made visible. So it
+ * will stay closed or hidden if it is not opened or not visible.
+ *
+ * @see ShowOperation
+ */
+ public abstract void show(@NullAllowed Set operations);
+
+ private static class Impl
+ extends InputOutput {
+
+ private final Map cache
+ = Collections.synchronizedMap(
+ new WeakHashMap());
+
+ private final InputOutputProvider provider;
+ private final IO ioObject;
+
+ public Impl(InputOutputProvider provider, IO ioObject) {
+
+ this.provider = provider;
+ this.ioObject = ioObject;
+ }
+
+ @Override
+ public Reader getIn() {
+ return provider.getIn(ioObject);
+ }
+
+ @Override
+ public OutputWriter getOut() {
+ return createOrGetCachedWrapper(provider.getOut(ioObject));
+ }
+
+ @Override
+ public OutputWriter getErr() {
+ return createOrGetCachedWrapper(provider.getErr(ioObject));
+ }
+
+ @Override
+ @NonNull
+ public Lookup getLookup() {
+ return provider.getIOLookup(ioObject);
+ }
+
+ @Override
+ public void reset() {
+ provider.resetIO(ioObject);
+ }
+
+ private OutputWriter createOrGetCachedWrapper(OW pw) {
+ OutputWriter ow = cache.get(pw);
+ if (ow == null) {
+ ow = OutputWriter.create(provider, ioObject, pw);
+ cache.put(pw, ow);
+ }
+ return ow;
+ }
+
+ @Override
+ public void close() {
+ provider.closeIO(ioObject);
+ }
+
+ @Override
+ public boolean isClosed() {
+ return provider.isIOClosed(ioObject);
+ }
+
+ @Override
+ public String getDescription() {
+ return provider.getIODescription(ioObject);
+ }
+
+ @Override
+ public void setDescription(String description) {
+ provider.setIODescription(ioObject, description);
+ }
+
+ @Override
+ public void show(Set operations) {
+ provider.showIO(ioObject,
+ operations != null
+ ? operations
+ : Collections.emptySet());
+ }
+ }
+}
diff --git a/api.io/src/org/netbeans/api/io/OutputColor.java b/api.io/src/org/netbeans/api/io/OutputColor.java
new file mode 100644
--- /dev/null
+++ b/api.io/src/org/netbeans/api/io/OutputColor.java
@@ -0,0 +1,198 @@
+/*
+ * 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 org.netbeans.spi.io.support.OutputColorType;
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.modules.io.OutputColorAccessor;
+
+/**
+ * A color specified for part of text in output pane. It can be a predefined
+ * color for some type of text (success, debug, warning, failure), or arbitrary
+ * RGB color.
+ *
+ * Although using wide range of custom RGB colors may be tempting, predefined
+ * colors are recommended, as they can be configured to respect GUI theme in
+ * use.
+ *
+ *
+ * @author jhavlin
+ */
+public abstract class OutputColor {
+
+
+ private final OutputColorType type;
+ private static final OutputColor CLR_WARNING = new TypeColor(OutputColorType.WARNING);
+ private static final OutputColor CLR_FAILURE = new TypeColor(OutputColorType.FAILURE);
+ private static final OutputColor CLR_DEBUG = new TypeColor(OutputColorType.DEBUG);
+ private static final OutputColor CLR_SUCCESS = new TypeColor(OutputColorType.SUCCESS);
+
+ static {
+ OutputColorAccessor.setDefault(new OutputColorAccessorImpl());
+ }
+
+ private OutputColor(OutputColorType type) {
+ this.type = type;
+ }
+
+ OutputColorType getType() {
+ return type;
+ }
+
+ /**
+ * Warning text color.
+ *
+ * @return Predefined color for text of type "warning".
+ */
+ @NonNull
+ public static OutputColor warning() {
+ return CLR_WARNING;
+ }
+
+ /**
+ * Failure text color.
+ *
+ * @return Predefined color for text of type "failure".
+ */
+ @NonNull
+ public static OutputColor failure() {
+ return CLR_FAILURE;
+ }
+
+ /**
+ * Debug text color.
+ *
+ * @return Predefined color for text of type "debug".
+ */
+ @NonNull
+ public static OutputColor debug() {
+ return CLR_DEBUG;
+ }
+
+ /**
+ * Success text color.
+ *
+ * @return Predefined color for text of type "success".
+ */
+ @NonNull
+ public static OutputColor success() {
+ return CLR_SUCCESS;
+ }
+
+ /**
+ * Arbitrary constant RGB color.
+ *
+ *
+ * Please note that it is recommended to use colors for predefined text
+ * types, which can respect color theme used by the GUI.
+ *
+ *
+ * @param r The red component, in the range (0 - 255).
+ * @param g The green component, in the range (0 - 255).
+ * @param b The blue component, in the range (0 - 255).
+ *
+ * @return Color specified for a constant RGB value.
+ * @throws IllegalArgumentException If some of color components is out of
+ * range.
+ */
+ @NonNull
+ public static OutputColor rgb(int r, int g, int b) {
+ checkColorComponentRange("r", r);
+ checkColorComponentRange("g", g);
+ checkColorComponentRange("b", b);
+ int value = ((r & 0xFF) << 16)
+ | ((g & 0xFF) << 8)
+ | ((b & 0xFF));
+ return rgb(value);
+ }
+
+ /**
+ * Arbitrary constant RGB color. Creates an opaque sRGB color with the
+ * specified combined RGB value consisting of the red component in bits
+ * 16-23, the green component in bits 8-15, and the blue component in bits
+ * 0-7.
+ *
+ *
+ * Please note that it is recommended to use colors for predefined text
+ * types, which can respect color theme used by the GUI.
+ *
+ *
+ * @param rgbValue The combined RGB components.
+ *
+ * @return Color specified for a constant RGB value.
+ */
+ @NonNull
+ public static OutputColor rgb(int rgbValue) {
+ return new RgbColor(rgbValue);
+ }
+
+ private static void checkColorComponentRange(String name,
+ int colorComponent) {
+
+ if (colorComponent < 0 || colorComponent > 255) {
+ throw new IllegalArgumentException("Color component " + name//NOI18N
+ + " is out of range (0 - 255): " + colorComponent); //NOI18N
+ }
+ }
+
+ private static class TypeColor extends OutputColor {
+
+ public TypeColor(OutputColorType type) {
+ super(type);
+ }
+ }
+
+ @SuppressWarnings("PackageVisibleInnerClass")
+ static class RgbColor extends OutputColor {
+
+ private final int value;
+
+ public RgbColor(int value) {
+ super(OutputColorType.RGB);
+ this.value = value;
+ }
+
+ public int getRGB() {
+ return value;
+ }
+ }
+}
diff --git a/api.io/src/org/netbeans/api/io/OutputColorAccessorImpl.java b/api.io/src/org/netbeans/api/io/OutputColorAccessorImpl.java
new file mode 100644
--- /dev/null
+++ b/api.io/src/org/netbeans/api/io/OutputColorAccessorImpl.java
@@ -0,0 +1,68 @@
+/*
+ * 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 org.netbeans.modules.io.OutputColorAccessor;
+import org.netbeans.spi.io.support.OutputColorType;
+
+/**
+ * Implementation of accessor that enables retrieving information about output
+ * colors in SPI.
+ *
+ * @author jhavlin
+ */
+class OutputColorAccessorImpl extends OutputColorAccessor{
+
+ @Override
+ public OutputColorType getType(OutputColor color) {
+ return color.getType();
+ }
+
+ @Override
+ public int getRgb(OutputColor color) {
+ if (color instanceof OutputColor.RgbColor) {
+ return ((OutputColor.RgbColor) color).getRGB();
+ } else {
+ throw new IllegalArgumentException("Not an RGB color."); //NOI18N
+ }
+ }
+}
diff --git a/api.io/src/org/netbeans/api/io/OutputWriter.java b/api.io/src/org/netbeans/api/io/OutputWriter.java
new file mode 100644
--- /dev/null
+++ b/api.io/src/org/netbeans/api/io/OutputWriter.java
@@ -0,0 +1,366 @@
+/*
+ * 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.IOException;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Locale;
+import java.util.Set;
+import org.netbeans.api.annotations.common.NullAllowed;
+import org.netbeans.spi.io.InputOutputProvider;
+
+/**
+ * Extended {@link PrintWriter} for writing into output window or similar output
+ * GUI component. It can support features like color printing, hyperlinks, or
+ * folding.
+ *
+ *
+ * Methods of this class can be called in any thread.
+ *
+ *
+ * @author jhavlin
+ */
+public abstract class OutputWriter extends PrintWriter {
+
+ private OutputWriter() {
+ super(new DummyWriter());
+ }
+
+ /**
+ * Get current position in the output stream.
+ *
+ * @return The position.
+ */
+ public abstract Position getCurrentPosition();
+
+ /**
+ * Start a new fold. If a fold already exists, a nested fold will be
+ * created.
+ *
+ * @param expanded True if the fold should be expanded by default, false if
+ * it should be collapsed.
+ *
+ * @return The fold handle.
+ */
+ public abstract Fold startFold(boolean expanded);
+
+ /**
+ * Finish a fold. If it contains some unfinished nested folds, they will be
+ * finished as well.
+ *
+ * @param fold The fold to finish.
+ */
+ public abstract void endFold(Fold fold);
+
+ public abstract void print(String s, Hyperlink link, OutputColor color);
+
+ public abstract void print(String s, Hyperlink link);
+
+ public abstract void print(String s, OutputColor color);
+
+ public abstract void println(String s, Hyperlink link, OutputColor color);
+
+ public abstract void println(String s, Hyperlink link);
+
+ public abstract void println(String s, OutputColor color);
+
+ static OutputWriter create(
+ InputOutputProvider provider, IO io, OW writer) {
+
+ return new Impl(provider, io, writer);
+ }
+
+ private static class Impl
+ extends OutputWriter {
+
+ private final InputOutputProvider provider;
+ private final IO io;
+ private final OW writer;
+
+ public Impl(InputOutputProvider provider,
+ IO io, OW writer) {
+
+ this.provider = provider;
+ this.io = io;
+ this.writer = writer;
+ }
+
+ @Override
+ public Position getCurrentPosition() {
+ return Position.create(provider, io, writer,
+ provider.getCurrentPosition(io, writer));
+ }
+
+ @Override
+ public void print(String s, Hyperlink link, OutputColor color) {
+ provider.print(io, writer, s, link, color, false);
+ }
+
+ @Override
+ public void print(String s, Hyperlink link) {
+ provider.print(io, writer, s, link, null, false);
+ }
+
+ @Override
+ public void print(String s, OutputColor color) {
+ provider.print(io, writer, s, null, color, false);
+ }
+
+ @Override
+ public void println(String s, Hyperlink link, OutputColor color) {
+ provider.print(io, writer, s, link, color, true);
+ }
+
+ @Override
+ public void println(String s, Hyperlink link) {
+ provider.print(io, writer, s, link, null, true);
+ }
+
+ @Override
+ public void println(String s, OutputColor color) {
+ provider.print(io, writer, s, null, color, true);
+ }
+
+ @Override
+ public void flush() {
+ writer.flush();
+ }
+
+ @Override
+ public void close() {
+ writer.close();
+ }
+
+ @Override
+ public boolean checkError() {
+ return writer.checkError();
+ }
+
+ @Override
+ public void write(int c) {
+ writer.write(c);
+ }
+
+ @Override
+ public void write(char[] buf, int off, int len) {
+ writer.write(buf, off, len);
+ }
+
+ @Override
+ public void write(char[] buf) {
+ writer.write(buf);
+ }
+
+ @Override
+ public void write(String s, int off, int len) {
+ writer.write(s, off, len);
+ }
+
+ @Override
+ public void write(String s) {
+ writer.write(s);
+ }
+
+ @Override
+ public void print(boolean b) {
+ writer.print(b);
+ }
+
+ @Override
+ public void print(char c) {
+ writer.print(c);
+ }
+
+ @Override
+ public void print(int i) {
+ writer.print(i);
+ }
+
+ @Override
+ public void print(long l) {
+ writer.print(l);
+ }
+
+ @Override
+ public void print(float f) {
+ writer.print(f);
+ }
+
+ @Override
+ public void print(double d) {
+ writer.print(d);
+ }
+
+ @Override
+ @SuppressWarnings("ImplicitArrayToString")
+ public void print(char[] s) {
+ writer.print(s);
+ }
+
+ @Override
+ public void print(String s) {
+ writer.print(s);
+ }
+
+ @Override
+ public void print(Object obj) {
+ writer.print(obj);
+ }
+
+ @Override
+ public void println() {
+ writer.println();
+ }
+
+ @Override
+ public void println(boolean x) {
+ writer.println(x);
+ }
+
+ @Override
+ public void println(char x) {
+ writer.println(x);
+ }
+
+ @Override
+ public void println(int x) {
+ writer.println(x);
+ }
+
+ @Override
+ public void println(long x) {
+ writer.println(x);
+ }
+
+ @Override
+ public void println(float x) {
+ writer.println(x);
+ }
+
+ @Override
+ public void println(double x) {
+ writer.println(x);
+ }
+
+ @Override
+ @SuppressWarnings("ImplicitArrayToString")
+ public void println(char[] x) {
+ writer.println(x);
+ }
+
+ @Override
+ public void println(String x) {
+ writer.println(x);
+ }
+
+ @Override
+ public void println(Object x) {
+ writer.println(x);
+ }
+
+ @Override
+ public PrintWriter printf(String format, Object... args) {
+ return writer.printf(format, args);
+ }
+
+ @Override
+ public PrintWriter printf(Locale l, String format, Object... args) {
+ return writer.printf(l, format, args);
+ }
+
+ @Override
+ public PrintWriter format(String format, Object... args) {
+ return writer.format(format, args);
+ }
+
+ @Override
+ public PrintWriter format(Locale l, String format, Object... args) {
+ return writer.format(l, format, args);
+ }
+
+ @Override
+ public PrintWriter append(CharSequence csq) {
+ return writer.append(csq);
+ }
+
+ @Override
+ public PrintWriter append(CharSequence csq, int start, int end) {
+ return writer.append(csq, start, end);
+ }
+
+ @Override
+ public PrintWriter append(char c) {
+ return writer.append(c);
+ }
+
+ @Override
+ public Fold startFold(boolean expanded) {
+ F fold = provider.startFold(io, writer, expanded);
+ return Fold.create(provider, io, writer, fold);
+ }
+
+ @Override
+ public void endFold(Fold fold) {
+ if (fold != Fold.UNSUPPORTED) {
+ fold.endFold();
+ }
+ }
+ }
+
+ private static class DummyWriter extends Writer {
+
+ @Override
+ public void write(char[] cbuf, int off, int len) throws IOException {
+ }
+
+ @Override
+ public void flush() throws IOException {
+ }
+
+ @Override
+ public void close() throws IOException {
+ }
+ }
+}
diff --git a/api.io/src/org/netbeans/api/io/Position.java b/api.io/src/org/netbeans/api/io/Position.java
new file mode 100644
--- /dev/null
+++ b/api.io/src/org/netbeans/api/io/Position.java
@@ -0,0 +1,106 @@
+/*
+ * 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;
+
+/**
+ *
+ * Stored position in the output window.
+ *
+ *
+ * Methods of this class can be called in any thread.
+ *
+ *
+ * @author jhavlin
+ */
+public abstract class Position {
+
+ static final Position UNSUPPORTED = new Position() {
+
+ @Override
+ public void scrollTo() {
+ }
+ };
+
+ private Position() {
+ }
+
+ /**
+ * Scroll to this position.
+ */
+ public abstract void scrollTo();
+
+ static Position create(
+ InputOutputProvider provider, IO io,
+ OW writer, P position) {
+
+ if (position == null) {
+ return UNSUPPORTED;
+ } else {
+ return new Impl(provider, io, writer, position);
+ }
+ }
+
+ private static class Impl
+ extends Position {
+
+ private final InputOutputProvider provider;
+ private final IO io;
+ private final OW ow;
+ private final P position;
+
+ public Impl(InputOutputProvider provider, IO io, OW ow,
+ P position) {
+ this.provider = provider;
+ this.io = io;
+ this.ow = ow;
+ this.position = position;
+ }
+
+ @Override
+ public void scrollTo() {
+ provider.scrollTo(io, ow, position);
+ }
+ }
+}
diff --git a/api.io/src/org/netbeans/api/io/ShowOperation.java b/api.io/src/org/netbeans/api/io/ShowOperation.java
new file mode 100644
--- /dev/null
+++ b/api.io/src/org/netbeans/api/io/ShowOperation.java
@@ -0,0 +1,65 @@
+/*
+ * 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;
+
+/**
+ * Operations that should take part when showing a component. The actual
+ * behavior depends on implementation (some features may be unsupported).
+ *
+ * @author jhavlin
+ */
+public enum ShowOperation {
+ /**
+ * Open the GUI component (Output Window) if it is closed.
+ */
+ OPEN,
+ /**
+ * Make the GUI component (Output Window) visible. E.g. show it if it is
+ * minimized.
+ */
+ MAKE_VISIBLE,
+ /**
+ * Activate the GUI component (Output Window). E.g. highlight and possibly
+ * focus it.
+ */
+ ACTIVATE
+}
diff --git a/api.io/src/org/netbeans/modules/io/HyperlinkAccessor.java b/api.io/src/org/netbeans/modules/io/HyperlinkAccessor.java
new file mode 100644
--- /dev/null
+++ b/api.io/src/org/netbeans/modules/io/HyperlinkAccessor.java
@@ -0,0 +1,86 @@
+/*
+ * 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.modules.io;
+
+import org.netbeans.api.io.Hyperlink;
+import org.netbeans.spi.io.support.HyperlinkType;
+
+/**
+ *
+ * @author jhavlin
+ */
+public abstract class HyperlinkAccessor {
+
+ /**
+ * The default implementation is set in static initializer of
+ * {@link Hyperlink}.
+ */
+ private static HyperlinkAccessor DEFAULT;
+
+ public static void setDefault(HyperlinkAccessor def) {
+ HyperlinkAccessor.DEFAULT = def;
+ }
+
+ public static HyperlinkAccessor getDefault() {
+ if (DEFAULT != null) {
+ return DEFAULT;
+ }
+
+ // invokes static initializer of Item.class
+ // that will assign value to the DEFAULT field above
+ Class c = Hyperlink.class;
+ try {
+ Class.forName(c.getName(), true, c.getClassLoader());
+ } catch (ClassNotFoundException ex) {
+ assert false : ex;
+ }
+ assert DEFAULT != null :
+ "The DEFAULT field must be initialized"; //NOI18N
+ return DEFAULT;
+ }
+
+ public abstract HyperlinkType getType(Hyperlink hyperlink);
+
+ public abstract boolean isImportant(Hyperlink hyperlink);
+
+ public abstract Runnable getRunnable(Hyperlink hyperlink);
+}
diff --git a/api.io/src/org/netbeans/modules/io/OutputColorAccessor.java b/api.io/src/org/netbeans/modules/io/OutputColorAccessor.java
new file mode 100644
--- /dev/null
+++ b/api.io/src/org/netbeans/modules/io/OutputColorAccessor.java
@@ -0,0 +1,84 @@
+/*
+ * 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.modules.io;
+
+import org.netbeans.api.io.OutputColor;
+import org.netbeans.spi.io.support.OutputColorType;
+
+/**
+ *
+ * @author jhavlin
+ */
+public abstract class OutputColorAccessor {
+
+ /**
+ * The default implementation is set in static initializer of
+ * {@link OutputColor}.
+ */
+ private static OutputColorAccessor DEFAULT;
+
+ public static void setDefault(OutputColorAccessor def) {
+ OutputColorAccessor.DEFAULT = def;
+ }
+
+ public static OutputColorAccessor getDefault() {
+ if (DEFAULT != null) {
+ return DEFAULT;
+ }
+
+ // invokes static initializer of Item.class
+ // that will assign value to the DEFAULT field above
+ Class c = OutputColor.class;
+ try {
+ Class.forName(c.getName(), true, c.getClassLoader());
+ } catch (ClassNotFoundException ex) {
+ assert false : ex;
+ }
+ assert DEFAULT != null :
+ "The DEFAULT field must be initialized"; //NOI18N
+ return DEFAULT;
+ }
+
+ public abstract OutputColorType getType(OutputColor color);
+
+ public abstract int getRgb(OutputColor color);
+}
diff --git a/api.io/src/org/netbeans/spi/io/InputOutputProvider.java b/api.io/src/org/netbeans/spi/io/InputOutputProvider.java
new file mode 100644
--- /dev/null
+++ b/api.io/src/org/netbeans/spi/io/InputOutputProvider.java
@@ -0,0 +1,329 @@
+/*
+ * 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.io;
+
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.util.Set;
+import org.netbeans.api.annotations.common.CheckForNull;
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.api.annotations.common.NullAllowed;
+import org.netbeans.api.io.Hyperlink;
+import org.netbeans.api.io.InputOutput;
+import org.netbeans.api.io.OutputColor;
+import org.netbeans.api.io.ShowOperation;
+import org.openide.util.Lookup;
+import org.openide.util.lookup.ServiceProvider;
+
+/**
+ *
+ * SPI for custom output window implementations.
+ *
+ * Use {@link ServiceProvider} annotation for registration.
+ *
+ *
+ *
+ * Note: Methods of this interface can be called in any thread by the
+ * infrastructure, so implementations should ensure proper synchronization.
+ *
+ *
+ * @author jhavlin
+ *
+ * @param Type of objects that will represent I/O instances (e.g. tabs in
+ * output window).
+ * @param Type of writers for standard and error streams.
+ * @param Type of object that describes position of a character in the
+ * output window. If the implementation does not support this type of
+ * information, use {@link Void} here.
+ * @param Type of object that describes a fold in output window. If the
+ * implementation does not support this type of information, use {@link Void}
+ * here.
+ */
+public interface InputOutputProvider {
+
+ /**
+ * Get identifier of this provider.
+ *
+ * @return Name of this provider, never null.
+ */
+ @NonNull
+ String getId();
+
+ /**
+ * Get or create an object that encapsulates state of a single I/O instance
+ * (e.g. tab in output window).
+ *
+ * @param name Display name of the output pane.
+ * @param newIO True to always create new I/O, false to return already
+ * existing instance if available.
+ * @param lookup Lookup with additional information.
+ *
+ * @return A single I/O instance, a newly created or already existing.
+ * @see InputOutput
+ */
+ @NonNull
+ IO getIO(@NonNull String name, boolean newIO, @NonNull Lookup lookup);
+
+ /**
+ * Get input of the passed I/O.
+ *
+ * @param io I/O instance.
+ *
+ * @return {@link Reader} Reader for the input entered in the output pane.
+ */
+ @NonNull
+ Reader getIn(@NonNull IO io);
+
+ /**
+ * Get output stream of the passed I/O.
+ *
+ * @param io I/O instance.
+ *
+ * @return {@link PrintWriter} for the output stream.
+ */
+ @NonNull
+ WRITER getOut(@NonNull IO io);
+
+ /**
+ * Get error stream of the passed I/O.
+ *
+ * @param io The I/O instance.
+ *
+ * @return {@link PrintWriter} for the error stream.
+ */
+ @NonNull
+ WRITER getErr(@NonNull IO io);
+
+ /**
+ * Print enhanced text. It can represent a clickable hyperlink, and can be
+ * assigned some color.
+ *
+ *
+ * If the implementation doesn't support this feature, this method should
+ * call something like
+ * {@code writer.print(text); if (printLineEnd) {writer.println();}}.
+ *
+ *
+ * @param io The I/O instance.
+ * @param writer The Stream to write into.
+ * @param text Text to print.
+ * @param link Link which should be represented by the text, can be null for
+ * standard text.
+ * @param color Color of the text, can be null for the default color of the
+ * stream.
+ * @param printLineEnd True if new-line should be appended after printing
+ * {code text}.
+ */
+ void print(@NonNull IO io, @NonNull WRITER writer, @NullAllowed String text,
+ @NullAllowed Hyperlink link, @NullAllowed OutputColor color,
+ boolean printLineEnd);
+
+ /**
+ * Get lookup of an I/O instance, which can contain various extensions and
+ * additional info.
+ *
+ * @param io The I/O instance.
+ *
+ * @return The lookup, which can be empty, but never null.
+ */
+ @NonNull
+ Lookup getIOLookup(@NonNull IO io);
+
+ /**
+ * Reset the I/O. Clear previously written data and prepare it for new data.
+ *
+ * If the implementation doesn't support this feature, this method should do
+ * nothing.
+ *
+ *
+ * @param io The I/O instance.
+ */
+ void resetIO(@NonNull IO io);
+
+ /**
+ * Show output pane for the passed I/O instance.
+ *
+ * If the implementation doesn't support this feature, this method should do
+ * nothing.
+ *
+ *
+ * @param io The I/O instance.
+ * @param operations Operations that should be performed to show the output.
+ * If the set is empty, the output pane (e.g. tab) can be selected, but no
+ * GUI component should be shown or made visible if it is currently closed
+ * or hidden.
+ *
+ * @see ShowOperation
+ */
+ void showIO(@NonNull IO io,
+ Set operations);
+
+ /**
+ * Close the I/O, its output pane and release resources.
+ *
+ * @param io The I/O instance.
+ *
+ * @see #isIOClosed(java.lang.Object)
+ */
+ void closeIO(@NonNull IO io);
+
+ /**
+ * Check whether the I/O is closed.
+ *
+ * @param io The I/O instance.
+ *
+ * @return True if the I/O was closed, false otherwise.
+ *
+ * @see #closeIO(java.lang.Object)
+ */
+ boolean isIOClosed(@NonNull IO io);
+
+ /**
+ * Get current position.
+ *
+ * @param io The I/O instance.
+ * @param writer Output or error writer. If the streams are merged, the
+ * value can be ignored.
+ *
+ * @return The current position in the output pane. If this feature is not
+ * supported, return null.
+ */
+ @CheckForNull
+ POS getCurrentPosition(@NonNull IO io, @NonNull WRITER writer);
+
+ /**
+ * Scroll to a position.
+ *
+ * If this feature is not supported
+ * ({@link #getCurrentPosition(Object, PrintWriter)} returns null), this
+ * method should do nothing, it will be never called.
+ *
+ *
+ * @param io The I/O instance.
+ * @param writer Output or error writer. If the streams are merged, the
+ * value can be ignored.
+ * @param position The position to scroll to.
+ *
+ * @see #getCurrentPosition(java.lang.Object, java.io.PrintWriter)
+ */
+ void scrollTo(@NonNull IO io, @NonNull WRITER writer,
+ @NonNull POS position);
+
+ /**
+ * Start fold at the current position. If a fold is already open, start a
+ * new nested fold (but if a fold with the same start position already
+ * exists, no nested fold will be created, and the same start position will
+ * be returned).
+ *
+ * @param io The I/O instance.
+ * @param writer Output or error writer. If the streams are merged, the
+ * value can be ignored.
+ * @param expanded True if the new fold should be expanded by default, false
+ * if it should be collapsed.
+ *
+ * @return Object the fold. If the implementation doesn't support this
+ * feature, return null.
+ */
+ @CheckForNull
+ FOLD startFold(@NonNull IO io, @NonNull WRITER writer, boolean expanded);
+
+ /**
+ * Finish a fold specified by its start position. If some nested folds
+ * exist, they will be finished as well if needed.
+ *
+ *
+ * If this feature is not supported
+ * ({@link #startFold(Object, PrintWriter, boolean)} returns null), this
+ * method should do nothing, it will be never called.
+ *
+ *
+ * @param io The I/O instance.
+ * @param writer Output or error writer. If the streams are merged, the
+ * value can be ignored.
+ * @param fold The fold to finish.
+ */
+ void endFold(@NonNull IO io, @NonNull WRITER writer,
+ @NonNull FOLD fold);
+
+ /**
+ * Expand or collapse a fold.
+ *
+ *
+ * If this feature is not supported
+ * ({@link #startFold(Object, PrintWriter, boolean)} returns null), this
+ * method should do nothing, it will be never called.
+ *
+ *
+ * @param io The I/O instance.
+ * @param writer Output or error writer. If the streams are merged, the
+ * value can be ignored.
+ * @param fold The fold to finish.
+ * @param expanded True to expand the fold, false to collapse the fold.
+ */
+ void setFoldExpanded(@NonNull IO io, @NonNull WRITER writer,
+ FOLD fold, boolean expanded);
+
+
+ /**
+ * Get description of an I/O instance. It can be used e.g. as tooltip text
+ * for the output tab.
+ *
+ * @param io The I/O instance.
+ *
+ * @return The description, or null if not set.
+ */
+ @CheckForNull String getIODescription(@NonNull IO io);
+
+ /**
+ * Set description of an I/O instance.
+ *
+ *
+ * If this feature is not supported, this method should do nothing.
+ *
+ *
+ * @param io The I/O instance.
+ * @param description The description, can be null.
+ *
+ * @see #getIODescription(java.lang.Object)
+ */
+ void setIODescription(@NonNull IO io, @NullAllowed String description);
+}
diff --git a/api.io/src/org/netbeans/spi/io/support/HyperlinkType.java b/api.io/src/org/netbeans/spi/io/support/HyperlinkType.java
new file mode 100644
--- /dev/null
+++ b/api.io/src/org/netbeans/spi/io/support/HyperlinkType.java
@@ -0,0 +1,54 @@
+/*
+ * 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.io.support;
+
+/**
+ * Type of the hyperlink.
+ *
+ * Note: New items may be added in the future.
+ *
+ *
+ * @author jhavlin
+ */
+public enum HyperlinkType {
+ FROM_RUNNABLE
+}
diff --git a/api.io/src/org/netbeans/spi/io/support/Hyperlinks.java b/api.io/src/org/netbeans/spi/io/support/Hyperlinks.java
new file mode 100644
--- /dev/null
+++ b/api.io/src/org/netbeans/spi/io/support/Hyperlinks.java
@@ -0,0 +1,97 @@
+/*
+ * 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.io.support;
+
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.api.io.Hyperlink;
+import org.netbeans.modules.io.HyperlinkAccessor;
+
+/**
+ * Helper class for accessing information from {@link Hyperlink} objects.
+ *
+ * @author jhavlin
+ */
+public final class Hyperlinks {
+
+ private Hyperlinks() {
+ }
+
+ /**
+ * Get hyperlink type.
+ *
+ * @param hyperlink The hyperlink to get type of.
+ * @return The type of the hyperlink.
+ */
+ @NonNull
+ public static HyperlinkType getType(@NonNull Hyperlink hyperlink) {
+ return HyperlinkAccessor.getDefault().getType(hyperlink);
+ }
+
+ /**
+ * Check whether a hyperlink is important.
+ *
+ * @param hyperlink The hyperlink to check.
+ *
+ * @return True if the hyperlink has been marked as important, false if it
+ * is a standard link.
+ */
+ public static boolean isImportant(@NonNull Hyperlink hyperlink) {
+ return HyperlinkAccessor.getDefault().isImportant(hyperlink);
+ }
+
+ /**
+ * Get runnable associated with a hyperlink of type
+ * {@link HyperlinkType#FROM_RUNNABLE}.
+ *
+ * @param hyperlink The hyperlink to get runnable from.
+ *
+ * @return A runnable.
+ * @throws IllegalArgumentException if type of the hyperlink is not
+ * {@link HyperlinkType#FROM_RUNNABLE}.
+ * @see #getType(org.netbeans.api.io.Hyperlink)
+ * @see HyperlinkType
+ */
+ @NonNull
+ public static Runnable getRunnable(@NonNull Hyperlink hyperlink) {
+ return HyperlinkAccessor.getDefault().getRunnable(hyperlink);
+ }
+}
diff --git a/api.io/src/org/netbeans/spi/io/support/OutputColorType.java b/api.io/src/org/netbeans/spi/io/support/OutputColorType.java
new file mode 100644
--- /dev/null
+++ b/api.io/src/org/netbeans/spi/io/support/OutputColorType.java
@@ -0,0 +1,54 @@
+/*
+ * 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.io.support;
+
+/**
+ * Type of the color - static (rgb) or dynamic.
+ *
+ * Note: New items may be added in the future.
+ *
+ *
+ * @author jhavlin
+ */
+public enum OutputColorType {
+ WARNING, FAILURE, DEBUG, SUCCESS, RGB
+}
diff --git a/api.io/src/org/netbeans/spi/io/support/OutputColors.java b/api.io/src/org/netbeans/spi/io/support/OutputColors.java
new file mode 100644
--- /dev/null
+++ b/api.io/src/org/netbeans/spi/io/support/OutputColors.java
@@ -0,0 +1,83 @@
+/*
+ * 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.io.support;
+
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.api.io.OutputColor;
+import org.netbeans.modules.io.OutputColorAccessor;
+
+/**
+ * Helper class for accessing information from {@link OutputColor} objects.
+ *
+ * @author jhavlin
+ */
+public final class OutputColors {
+
+ private OutputColors() {
+ }
+
+ /**
+ * Get type of a color.
+ *
+ * @param color The color to get type of.
+ * @return Type of color.
+ */
+ @NonNull
+ public static OutputColorType getType(@NonNull OutputColor color) {
+ return OutputColorAccessor.getDefault().getType(color);
+ }
+
+ /**
+ * Get RGB value for an {@link OutputColor} specified for a constant RGB
+ * color (type {@link OutputColorType#RGB}).
+ *
+ * @param color The color to get RGB value for.
+ *
+ * @return RGB value of the color.
+ * @throws IllegalArgumentException if the color is not of type
+ * {@link OutputColorType#RGB}.
+ */
+ public static int getRGB(OutputColor color) {
+ return OutputColorAccessor.getDefault().getRgb(color);
+ }
+
+}
diff --git a/api.io/test/unit/src/org/netbeans/api/io/HyperlinkTest.java b/api.io/test/unit/src/org/netbeans/api/io/HyperlinkTest.java
new file mode 100644
--- /dev/null
+++ b/api.io/test/unit/src/org/netbeans/api/io/HyperlinkTest.java
@@ -0,0 +1,82 @@
+/*
+ * 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 static org.junit.Assert.*;
+import org.junit.Test;
+import org.netbeans.spi.io.support.HyperlinkType;
+import org.netbeans.spi.io.support.Hyperlinks;
+
+/**
+ *
+ * @author jhavlin
+ */
+public class HyperlinkTest {
+
+ @Test
+ public void testOnClickLink() {
+
+ final boolean[] invoked = new boolean[1];
+ Hyperlink h = Hyperlink.from(new Runnable() {
+
+ @Override
+ public void run() {
+ invoked[0] = true;
+ }
+ });
+ assertTrue(Hyperlinks.getType(h) == HyperlinkType.FROM_RUNNABLE);
+ assertFalse(h.isImportant());
+ assertNotNull(Hyperlinks.getRunnable(h));
+ Hyperlinks.getRunnable(h).run();
+ assertTrue("The passed code should be invoked", invoked[0]);
+ }
+
+ @Test
+ public void testOnClickLinkImportant() {
+ Hyperlink h = Hyperlink.from(new Runnable() {
+ @Override
+ public void run() {
+ }
+ }, true);
+ assertTrue(h.isImportant());
+ }
+}
diff --git a/api.io/test/unit/src/org/netbeans/api/io/IOProviderTest.java b/api.io/test/unit/src/org/netbeans/api/io/IOProviderTest.java
new file mode 100644
--- /dev/null
+++ b/api.io/test/unit/src/org/netbeans/api/io/IOProviderTest.java
@@ -0,0 +1,286 @@
+/*
+ * 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 java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Set;
+import org.junit.Test;
+import static org.junit.Assert.*;
+import org.netbeans.junit.MockServices;
+import org.netbeans.spi.io.InputOutputProvider;
+import org.openide.util.Lookup;
+import org.openide.util.lookup.Lookups;
+
+/**
+ *
+ * @author jhavlin
+ */
+public class IOProviderTest {
+
+ public IOProviderTest() {
+ }
+
+ @Test
+ public void useCase1() {
+ InputOutput io = IOProvider.getDefault().getIO("UseCase1", true);
+ io.getOut().println("This is a simple output");
+ io.getOut().close();
+ }
+
+ @Test
+ public void useCase2() {
+ InputOutput io = IOProvider.getDefault().getIO("UseCase2", false);
+ io.getOut().print("A line containing a ");
+ io.getOut().print("hyperlink", Hyperlink.from(new Runnable() {
+
+ @Override
+ public void run() {
+ // some action
+ }
+ }));
+ io.getOut().println(" for a URI.");
+ io.getOut().close();
+ }
+
+ @Test
+ public void useCase3() {
+ InputOutput io = IOProvider.getDefault().getIO("UseCase3", true);
+ io.getOut().print("A line containing a ");
+ io.getOut().print("hyperlink", Hyperlink.from(new Runnable() {
+ @Override
+ public void run() {
+ System.gc();
+ }
+ }));
+ io.getOut().println(" for invokation of custom code.");
+ io.getOut().close();
+ }
+
+ @Test
+ public void useCase4() {
+ InputOutput io = IOProvider.getDefault().getIO("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();
+ }
+
+ @Test
+ public void useCase5() {
+ InputOutput io = IOProvider.getDefault().getIO("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();
+ }
+
+ @Test
+ public void testTrivialImplementationAlwaysAvailable() {
+ assertEquals("Trivial", IOProvider.getDefault().getId());
+ assertEquals("Trivial", IOProvider.get("Trivial").getId());
+ assertEquals("Trivial", IOProvider.get("Another").getId());
+ }
+
+ @Test
+ public void testGetFromLookup() {
+ MockServices.setServices(MockInputOutputProvider.class);
+ try {
+ assertEquals("mock", IOProvider.getDefault().getId());
+ assertEquals("mock", IOProvider.get("mock").getId());
+ assertEquals("mock", IOProvider.get("wrong").getId());
+ } finally {
+ MockServices.setServices();
+ }
+ }
+
+ @Test
+ public void testAllMethodsAreDelegatedToSPI() {
+ MockServices.setServices(MockInputOutputProvider.class);
+ try {
+ IOProvider.getDefault().getIO("test1", true);
+ Lookup lkp = IOProvider.getDefault()
+ .getIO("test1", false, Lookup.EMPTY).getLookup();
+ CalledMethodList list = lkp.lookup(CalledMethodList.class);
+ assertEquals("getIO", list.get(0));
+ assertEquals("getIO", list.get(1));
+ assertEquals("getIOLookup", list.get(2));
+ assertEquals(3, list.size());
+ } finally {
+ MockServices.setServices();
+ }
+ }
+
+ @SuppressWarnings("PackageVisibleInnerClass")
+ static class CalledMethodList extends ArrayList {
+ }
+
+ @SuppressWarnings("PublicInnerClass")
+ public static class MockInputOutputProvider implements
+ InputOutputProvider {
+
+ private final CalledMethodList calledMethods = new CalledMethodList();
+ private final StringWriter stringWriter = new StringWriter();
+ private final Lookup lookup = Lookups.fixed(calledMethods, stringWriter);
+
+ @Override
+ public String getId() {
+ return "mock";
+ }
+
+ @Override
+ public Object getIO(String name, boolean newIO, Lookup lookup) {
+ calledMethods.add("getIO");
+ return new Object();
+ }
+
+ @Override
+ public Reader getIn(Object io) {
+ calledMethods.add("getIn");
+ return new StringReader("");
+ }
+
+ @Override
+ public PrintWriter getOut(Object io) {
+ calledMethods.add("getOut");
+ return new PrintWriter(stringWriter);
+ }
+
+ @Override
+ public PrintWriter getErr(Object io) {
+ calledMethods.add("getErr");
+ return new PrintWriter(stringWriter);
+ }
+
+ @Override
+ public void print(Object io, PrintWriter writer, String text,
+ Hyperlink link, OutputColor color, boolean printLineEnd) {
+ if (link != null || color != null) {
+ stringWriter.append("");
+ }
+ stringWriter.append(text);
+ if (link != null || color != null) {
+ stringWriter.append(" ");
+ }
+ calledMethods.add("print");
+ if (printLineEnd) {
+ stringWriter.append(System.getProperty("line.separator"));
+ }
+ }
+
+ @Override
+ public Lookup getIOLookup(Object io) {
+ calledMethods.add("getIOLookup");
+ return lookup;
+ }
+
+ @Override
+ public void resetIO(Object io) {
+ calledMethods.add("resetIO");
+ }
+
+ @Override
+ public void showIO(Object io,
+ Set operations) {
+ calledMethods.add("showIO");
+ }
+
+ @Override
+ public void closeIO(Object io) {
+ calledMethods.add("closeIO");
+ }
+
+ @Override
+ public boolean isIOClosed(Object io) {
+ calledMethods.add("isIOClosed");
+ return false;
+ }
+
+ @Override
+ public Object getCurrentPosition(Object io, PrintWriter writer) {
+ calledMethods.add("getCurrentPosition");
+ return new Object();
+ }
+
+ @Override
+ public void scrollTo(Object io, PrintWriter writer, Object position) {
+ calledMethods.add("scrollTo");
+ }
+
+ @Override
+ public Object startFold(Object io, PrintWriter writer, boolean expanded) {
+ calledMethods.add("startFold");
+ return new Object();
+ }
+
+ @Override
+ public void endFold(Object io, PrintWriter writer, Object foldNumber) {
+ calledMethods.add("endFold");
+ }
+
+ @Override
+ public void setFoldExpanded(Object io, PrintWriter writer,
+ Object foldNumber, boolean expanded) {
+ calledMethods.add("setFoldExpanded");
+ }
+
+ @Override
+ public String getIODescription(Object io) {
+ calledMethods.add("getIODescription");
+ return null;
+ }
+
+ @Override
+ public void setIODescription(Object io, String description) {
+ calledMethods.add("setIODescription");
+ }
+ }
+}
diff --git a/api.io/test/unit/src/org/netbeans/api/io/InputOutputTest.java b/api.io/test/unit/src/org/netbeans/api/io/InputOutputTest.java
new file mode 100644
--- /dev/null
+++ b/api.io/test/unit/src/org/netbeans/api/io/InputOutputTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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 org.junit.Test;
+import static org.junit.Assert.*;
+import org.netbeans.junit.MockServices;
+import org.openide.util.Lookup;
+
+/**
+ *
+ * @author jhavlin
+ */
+public class InputOutputTest {
+
+ public InputOutputTest() {
+ }
+
+ @Test
+ @SuppressWarnings("ValueOfIncrementOrDecrementUsed")
+ public void testAllMethodsAreDelegatedToSPI() {
+ MockServices.setServices(IOProviderTest.MockInputOutputProvider.class);
+ try {
+ InputOutput io = IOProvider.getDefault().getIO("test1", true);
+ io.getIn();
+ io.getOut();
+ io.getErr();
+ io.reset();
+ io.isClosed();
+ io.close();
+ io.getDescription();
+ io.setDescription(null);
+ Lookup lkp = io.getLookup();
+ IOProviderTest.CalledMethodList list
+ = lkp.lookup(IOProviderTest.CalledMethodList.class);
+
+ int order = 0;
+ assertEquals("getIO", list.get(order++));
+ assertEquals("getIn", list.get(order++));
+ assertEquals("getOut", list.get(order++));
+ assertEquals("getErr", list.get(order++));
+ assertEquals("resetIO", list.get(order++));
+ assertEquals("isIOClosed", list.get(order++));
+ assertEquals("closeIO", list.get(order++));
+ assertEquals("getIODescription", list.get(order++));
+ assertEquals("setIODescription", list.get(order++));
+ assertEquals("getIOLookup", list.get(order++));
+ } finally {
+ MockServices.setServices();
+ }
+ }
+}
diff --git a/api.io/test/unit/src/org/netbeans/api/io/OutputColorTest.java b/api.io/test/unit/src/org/netbeans/api/io/OutputColorTest.java
new file mode 100644
--- /dev/null
+++ b/api.io/test/unit/src/org/netbeans/api/io/OutputColorTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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 org.netbeans.spi.io.support.OutputColorType;
+import org.junit.Test;
+import static org.junit.Assert.*;
+import org.netbeans.spi.io.support.OutputColors;
+
+/**
+ *
+ * @author jhavlin
+ */
+public class OutputColorTest {
+
+ @Test
+ public void testRgbColor() {
+ OutputColor c = OutputColor.rgb(127, 255, 1);
+ assertEquals(OutputColorType.RGB, OutputColors.getType(c));
+ int value = OutputColors.getRGB(c);
+ int r = value >> 16;
+ int g = value >> 8 & 0xFF;
+ int b = value & 0xFF;
+ assertEquals(127, r);
+ assertEquals(255, g);
+ assertEquals(1, b);
+ }
+
+ @Test
+ public void testWarningColor() {
+ OutputColor c = OutputColor.warning();
+ assertEquals(OutputColorType.WARNING, c.getType());
+ }
+
+ @Test
+ public void testFailureColor() {
+ OutputColor c = OutputColor.failure();
+ assertEquals(OutputColorType.FAILURE, c.getType());
+ }
+
+ @Test
+ public void testDebugColor() {
+ OutputColor c = OutputColor.debug();
+ assertEquals(OutputColorType.DEBUG, c.getType());
+ }
+
+ @Test
+ public void testSuccessColor() {
+ OutputColor c = OutputColor.success();
+ assertEquals(OutputColorType.SUCCESS, c.getType());
+ }
+}
diff --git a/api.io/test/unit/src/org/netbeans/api/io/OutputWriterTest.java b/api.io/test/unit/src/org/netbeans/api/io/OutputWriterTest.java
new file mode 100644
--- /dev/null
+++ b/api.io/test/unit/src/org/netbeans/api/io/OutputWriterTest.java
@@ -0,0 +1,134 @@
+/*
+ * 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.StringWriter;
+import org.junit.Test;
+import static org.junit.Assert.*;
+import org.netbeans.junit.MockServices;
+import org.openide.util.Lookup;
+
+/**
+ *
+ * @author jhavlin
+ */
+public class OutputWriterTest {
+
+ public OutputWriterTest() {
+ }
+
+ @Test
+ @SuppressWarnings("ValueOfIncrementOrDecrementUsed")
+ public void testAllMethodsAreDelegatedToSPI() {
+ MockServices.setServices(IOProviderTest.MockInputOutputProvider.class);
+ try {
+
+ InputOutput io = IOProvider.getDefault().getIO("test1", true);
+ OutputWriter ow = io.getOut();
+ Lookup lkp = io.getLookup();
+
+ IOProviderTest.CalledMethodList list
+ = lkp.lookup(IOProviderTest.CalledMethodList.class);
+
+ io.show();
+ Position p = ow.getCurrentPosition();
+ p.scrollTo();
+ Fold f = ow.startFold(true);
+ f.expand();
+ f.collapse();
+ ow.endFold(f);
+
+ int order = 0;
+ assertEquals("getIO", list.get(order++));
+ assertEquals("getOut", list.get(order++));
+ assertEquals("getIOLookup", list.get(order++));
+ assertEquals("showIO", list.get(order++));
+ assertEquals("getCurrentPosition", list.get(order++));
+ assertEquals("scrollTo", list.get(order++));
+ assertEquals("startFold", list.get(order++));
+ assertEquals("setFoldExpanded", list.get(order++));
+ assertEquals("setFoldExpanded", list.get(order++));
+ assertEquals("endFold", list.get(order++));
+
+ ow.print("Line");
+ ow.print(" 1");
+ ow.println();
+
+ Runnable runnable = new Runnable() {
+
+ @Override
+ public void run() {
+ }
+ };
+
+ ow.print("Hyperlink ", Hyperlink.from(runnable));
+ ow.print(" ");
+ ow.print("Color", OutputColor.debug());
+ ow.print(" ");
+ ow.print("Color link", Hyperlink.from(runnable),
+ OutputColor.debug());
+ ow.println();
+
+ ow.println("Line with link", Hyperlink.from(runnable));
+ ow.println("Color line", OutputColor.debug());
+ ow.println("Color line with link",
+ Hyperlink.from(runnable), OutputColor.debug());
+
+ StringWriter sw = lkp.lookup(StringWriter.class);
+ sw.toString();
+
+ String[] lines = sw.toString().split(
+ System.getProperty("line.separator"));
+
+ assertEquals("Line 1", lines[0]);
+ assertEquals("Hyperlink Color "
+ + "Color link ", lines[1]);
+ assertEquals("Line with link ", lines[2]);
+ assertEquals("Color line ", lines[3]);
+ assertEquals("Color line with link ", lines[4]);
+
+ } finally {
+ MockServices.setServices();
+ }
+ }
+
+}
diff --git a/core.output2/manifest.mf b/core.output2/manifest.mf
--- a/core.output2/manifest.mf
+++ b/core.output2/manifest.mf
@@ -2,7 +2,7 @@
OpenIDE-Module: org.netbeans.core.output2/1
OpenIDE-Module-Layer: org/netbeans/core/output2/layer.xml
OpenIDE-Module-Localizing-Bundle: org/netbeans/core/output2/Bundle.properties
-OpenIDE-Module-Provides: org.openide.windows.IOProvider
+OpenIDE-Module-Provides: org.openide.windows.IOProvider org.netbeans.spi.io.InputOutputProvider
AutoUpdate-Essential-Module: true
OpenIDE-Module-Specification-Version: 1.38
diff --git a/core.output2/nbproject/project.xml b/core.output2/nbproject/project.xml
--- a/core.output2/nbproject/project.xml
+++ b/core.output2/nbproject/project.xml
@@ -50,6 +50,14 @@
org.netbeans.core.output2
+ org.netbeans.api.io
+
+
+
+ 1.0
+
+
+
org.netbeans.modules.options.api
@@ -111,7 +119,7 @@
- 1.40
+ 1.47
diff --git a/core.output2/src/org/netbeans/core/output2/NbIOProvider.java b/core.output2/src/org/netbeans/core/output2/NbIOProvider.java
--- a/core.output2/src/org/netbeans/core/output2/NbIOProvider.java
+++ b/core.output2/src/org/netbeans/core/output2/NbIOProvider.java
@@ -47,8 +47,12 @@
import java.io.IOException;
import java.util.WeakHashMap;
import javax.swing.Action;
+import org.netbeans.spi.io.InputOutputProvider;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
+import org.openide.util.lookup.ServiceProvider;
+import org.openide.util.lookup.ServiceProviders;
+import org.openide.windows.BridgingIOProvider;
import org.openide.windows.IOContainer;
import org.openide.windows.IOProvider;
import org.openide.windows.InputOutput;
@@ -58,8 +62,12 @@
* Supplies Output Window implementation through Lookup.
* @author Jesse Glick, Tim Boudreau
*/
-@org.openide.util.lookup.ServiceProvider(service=org.openide.windows.IOProvider.class, position=100)
-public final class NbIOProvider extends IOProvider {
+@ServiceProviders({
+ @ServiceProvider(service=IOProvider.class, position=100),
+ @ServiceProvider(service=InputOutputProvider.class, position=100)
+})
+public final class NbIOProvider extends BridgingIOProvider {
+
private static final WeakHashMap containerPairMaps =
new WeakHashMap();
diff --git a/nbbuild/build.properties b/nbbuild/build.properties
--- a/nbbuild/build.properties
+++ b/nbbuild/build.properties
@@ -100,6 +100,7 @@
config.javadoc.stable=\
api.annotations.common,\
api.html4j,\
+ api.io,\
api.maven,\
autoupdate.services,\
autoupdate.ui,\
diff --git a/nbbuild/cluster.properties b/nbbuild/cluster.properties
--- a/nbbuild/cluster.properties
+++ b/nbbuild/cluster.properties
@@ -195,6 +195,7 @@
nb.cluster.platform=\
api.annotations.common,\
api.html4j,\
+ api.io,\
api.progress,\
api.progress.compat8,\
api.progress.nb,\
diff --git a/nbbuild/javadoctools/links.xml b/nbbuild/javadoctools/links.xml
--- a/nbbuild/javadoctools/links.xml
+++ b/nbbuild/javadoctools/links.xml
@@ -240,3 +240,4 @@
+
diff --git a/nbbuild/javadoctools/properties.xml b/nbbuild/javadoctools/properties.xml
--- a/nbbuild/javadoctools/properties.xml
+++ b/nbbuild/javadoctools/properties.xml
@@ -239,3 +239,4 @@
+
diff --git a/nbbuild/javadoctools/replaces.xml b/nbbuild/javadoctools/replaces.xml
--- a/nbbuild/javadoctools/replaces.xml
+++ b/nbbuild/javadoctools/replaces.xml
@@ -239,3 +239,4 @@
+
diff --git a/openide.io/apichanges.xml b/openide.io/apichanges.xml
--- a/openide.io/apichanges.xml
+++ b/openide.io/apichanges.xml
@@ -107,6 +107,24 @@
+
+
+ Create a provider abstract class that implements new I/O SPI
+
+
+
+
+
+
+ As new API and SPI for output windows has been introduced, it is
+ useful to have a convenient way for implementators of the original
+ API to support the new API as well. The BridgingIOProvider class
+ implements both SPIs, and its JavaDoc explains how to use it.
+
+
+
+
+
Created new user-friendly methods for working with FoldHandle instances.
diff --git a/openide.io/manifest.mf b/openide.io/manifest.mf
--- a/openide.io/manifest.mf
+++ b/openide.io/manifest.mf
@@ -1,6 +1,6 @@
Manifest-Version: 1.0
OpenIDE-Module: org.openide.io
-OpenIDE-Module-Specification-Version: 1.46
+OpenIDE-Module-Specification-Version: 1.47
OpenIDE-Module-Localizing-Bundle: org/openide/io/Bundle.properties
OpenIDE-Module-Recommends: org.openide.windows.IOProvider, org.openide.windows.IOContainer$Provider
AutoUpdate-Essential-Module: true
diff --git a/openide.io/nbproject/org-openide-io.sig b/openide.io/nbproject/org-openide-io.sig
--- a/openide.io/nbproject/org-openide-io.sig
+++ b/openide.io/nbproject/org-openide-io.sig
@@ -1,5 +1,5 @@
#Signature file v4.1
-#Version 1.45
+#Version 1.44.1
CLSS public abstract interface java.io.Closeable
intf java.lang.AutoCloseable
diff --git a/openide.io/nbproject/project.xml b/openide.io/nbproject/project.xml
--- a/openide.io/nbproject/project.xml
+++ b/openide.io/nbproject/project.xml
@@ -59,11 +59,11 @@
- org.openide.util
+ org.netbeans.api.io
- 9.0
+ 1.0
@@ -71,7 +71,7 @@
- 9.0
+ 9.1
diff --git a/openide.io/src/org/openide/windows/BridgingIOProvider.java b/openide.io/src/org/openide/windows/BridgingIOProvider.java
new file mode 100644
--- /dev/null
+++ b/openide.io/src/org/openide/windows/BridgingIOProvider.java
@@ -0,0 +1,378 @@
+/*
+ * 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.openide.windows;
+
+import java.awt.Color;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.EnumSet;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.Action;
+import org.netbeans.api.io.Hyperlink;
+import org.netbeans.api.io.OutputColor;
+import org.netbeans.api.io.ShowOperation;
+import org.netbeans.spi.io.support.Hyperlinks;
+import org.netbeans.spi.io.InputOutputProvider;
+import org.netbeans.spi.io.support.OutputColorType;
+import org.netbeans.spi.io.support.OutputColors;
+import org.openide.util.Lookup;
+import org.openide.util.lookup.ServiceProvider;
+import org.openide.util.lookup.ServiceProviders;
+import org.openide.windows.IOColors.OutputType;
+import org.openide.windows.IOPosition.Position;
+
+/**
+ * Abstract class for easy support of {@link InputOutputProvider}, the SPI for
+ * the new I/O API.
+ *
+ * This class is useful if you have a custom implementation of Output Window,
+ * which uses SPI contained in this module ({@link IOProvider} and related
+ * interfaces), and want to your implementation also accessible via the new I/O
+ * API in module api.io.
+ *
+ *
+ * To start supporting the new API:
+ *
+ *
+ * Add dependency on module api.io (I/O API ans SPI,
+ * org.netbeans.api.io)
+ * Make your I/O provider extend {@link BridgingIOProvider} instead of
+ * {@link IOProvider}
+ * Add {@link ServiceProvider} annotation for {@link InputOutputProvider},
+ * {@link ServiceProviders} will be needed to allow multiple services:
+ *
+ *
+ * @ServiceProviders({
+ * @ServiceProvider(service=IOProvider.class, position=900),
+ * @ServiceProvider(service=InputOutputProvider.class, position=900)
+ * })
+ * public final class MyIOProvider extends BridgingIOProvider { ... }
+ *
+ *
+ * If needed, override some of the method to improve performance.
+ *
+ *
+ * @author jhavlin
+ */
+public abstract class BridgingIOProvider extends IOProvider
+ implements InputOutputProvider {
+
+ private static final Logger LOG
+ = Logger.getLogger(BridgingIOProvider.class.getName());
+
+ private final Deque foldStack = new ArrayDeque();
+
+ @Override
+ public String getId() {
+ return getName();
+ }
+
+ @Override
+ public InputOutput getIO(String name, boolean newIO, Lookup lookup) {
+ Action[] actions = lookup.lookup(Action[].class);
+ IOContainer container = lookup.lookup(IOContainer.class);
+ if (container == null && actions == null) {
+ return getIO(name, newIO);
+ } else if (newIO) {
+ if (container != null && actions != null) {
+ return getIO(name, actions, container);
+ } else if (actions != null) {
+ return getIO(name, actions);
+ } else {
+ return getIO(name, new Action[0], container);
+ }
+ } else {
+ return getIO(name, newIO, actions == null ? new Action[0] : actions,
+ container);
+ }
+ }
+
+ @Override
+ public Reader getIn(InputOutput io) {
+ return io.getIn();
+ }
+
+ @Override
+ public OutputWriter getOut(InputOutput io) {
+ return io.getOut();
+ }
+
+ @Override
+ public OutputWriter getErr(InputOutput io) {
+ return io.getErr();
+ }
+
+ @Override
+ public void print(InputOutput io, OutputWriter writer, String text,
+ Hyperlink link, OutputColor outputColor, boolean printLineEnd) {
+
+ Color awtColor = outputColorToAwtColor(io, outputColor);
+ OutputListener listener = hyperlinkToOutputListener(link);
+ boolean listenerImportant = link != null && Hyperlinks.isImportant(link);
+ try {
+ if (printLineEnd && outputColor == null) {
+ writer.println(text, listener, listenerImportant);
+ } else if (printLineEnd && IOColorLines.isSupported(io)) {
+ IOColorLines.println(io, text, listener, listenerImportant,
+ awtColor);
+ } else if (IOColorPrint.isSupported(io)) {
+ IOColorPrint.print(io, text, listener, listenerImportant,
+ awtColor);
+ if (printLineEnd) {
+ writer.println();
+ }
+ } else if (printLineEnd) {
+ writer.println(text);
+ } else {
+ writer.print(text);
+ }
+ } catch (IOException ex) {
+ LOG.log(Level.FINE, "Cannot print color or hyperlink", ex); //NOI18N
+ }
+ }
+
+ @Override
+ public Lookup getIOLookup(InputOutput io) {
+ if (io instanceof Lookup.Provider) {
+ return ((Lookup.Provider) io).getLookup();
+ } else {
+ return Lookup.EMPTY;
+ }
+ }
+
+ @Override
+ public void resetIO(InputOutput io) {
+ try {
+ io.getOut().reset();
+ } catch (IOException ex) {
+ LOG.log(Level.FINE, "Cannot reset InputOutput.", ex); //NOI18N
+ }
+ }
+
+ @Override
+ public void showIO(InputOutput io,
+ Set operations) {
+ if (operations.contains(ShowOperation.OPEN)
+ && operations.contains(ShowOperation.MAKE_VISIBLE)
+ && operations.size() == 2) {
+ io.select();
+ } else {
+ IOSelect.select(io, showOperationsToIoSelect(operations));
+ }
+ }
+
+ /**
+ * Translate set of {@link ShowOperation}s to set of
+ * {@link IOSelect.AdditionalOperation}s.
+ */
+ private Set showOperationsToIoSelect(
+ Set operations) {
+ Set res
+ = EnumSet.noneOf(IOSelect.AdditionalOperation.class);
+ for (ShowOperation so : operations) {
+ switch (so) {
+ case OPEN:
+ res.add(IOSelect.AdditionalOperation.OPEN);
+ break;
+ case MAKE_VISIBLE:
+ res.add(IOSelect.AdditionalOperation.REQUEST_VISIBLE);
+ break;
+ case ACTIVATE:
+ res.add(IOSelect.AdditionalOperation.REQUEST_ACTIVE);
+ break;
+ }
+ }
+ return res;
+ }
+
+ @Override
+ public void closeIO(InputOutput io) {
+ io.closeInputOutput();
+ }
+
+ @Override
+ public boolean isIOClosed(InputOutput io) {
+ return io.isClosed();
+ }
+
+ @Override
+ public Position getCurrentPosition(InputOutput io, OutputWriter writer) {
+ if (IOPosition.isSupported(io)) {
+ return IOPosition.currentPosition(io);
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public void scrollTo(InputOutput io, OutputWriter writer, Position position) {
+ position.scrollTo();
+ }
+
+ @Override
+ public FoldHandle startFold(InputOutput io, OutputWriter writer,
+ boolean expanded) {
+
+ if (IOFolding.isSupported(io)) {
+ synchronized (foldStack) {
+ if (foldStack.isEmpty()) {
+ foldStack.addLast(IOFolding.startFold(io, expanded));
+ } else {
+ foldStack.addLast(foldStack.getLast().startFold(expanded));
+ }
+ return foldStack.getLast();
+ }
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public void endFold(InputOutput io, OutputWriter writer, FoldHandle fold) {
+ synchronized (foldStack) {
+ while (!foldStack.isEmpty()) {
+ if (foldStack.removeLast() == fold) {
+ break;
+ }
+ }
+ fold.silentFinish();
+ }
+ }
+
+ @Override
+ public void setFoldExpanded(InputOutput io, OutputWriter writer,
+ FoldHandle fold, boolean expanded) {
+ fold.setExpanded(expanded);
+ }
+
+ @Override
+ public String getIODescription(InputOutput io) {
+ if (IOTab.isSupported(io)) {
+ return IOTab.getToolTipText(io);
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public void setIODescription(InputOutput io, String description) {
+ if (IOTab.isSupported(io)) {
+ IOTab.setToolTipText(io, description);
+ }
+ }
+
+ /**
+ * Convert a hyperlink to an output listener.
+ *
+ * @param link The hyperlink.
+ * @return The wrapping output listener.
+ */
+ private static OutputListener hyperlinkToOutputListener(
+ final Hyperlink link) {
+
+ if (link == null) {
+ return null;
+ }
+ switch (Hyperlinks.getType(link)) {
+ case FROM_RUNNABLE:
+ return new OutputListenerAdapter() {
+ @Override
+ public void outputLineAction(OutputEvent ev) {
+ Hyperlinks.getRunnable(link).run();
+ }
+ };
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Convert AWT-independent {@link OutputColor} to {@link java.awt.Color}.
+ *
+ * @return Appropriate color, or null if default color should be used.
+ */
+ private static Color outputColorToAwtColor(InputOutput io,
+ OutputColor color) {
+
+ if (color == null) {
+ return null;
+ }
+ OutputColorType type = OutputColors.getType(color);
+ if (type == OutputColorType.RGB) {
+ return new Color(OutputColors.getRGB(color));
+ } else if (IOColors.isSupported(io)) {
+ switch (type) {
+ case DEBUG:
+ return IOColors.getColor(io, OutputType.LOG_DEBUG);
+ case FAILURE:
+ return IOColors.getColor(io, OutputType.LOG_FAILURE);
+ case WARNING:
+ return IOColors.getColor(io, OutputType.LOG_WARNING);
+ case SUCCESS:
+ return IOColors.getColor(io, OutputType.LOG_SUCCESS);
+ default:
+ return null;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ private static class OutputListenerAdapter implements OutputListener {
+
+ @Override
+ public void outputLineSelected(OutputEvent ev) {
+ }
+
+ @Override
+ public void outputLineAction(OutputEvent ev) {
+ }
+
+ @Override
+ public void outputLineCleared(OutputEvent ev) {
+ }
+ }
+}