- * InputOutput io = ...;
- * if (!IOFolding.isSupported(io)) {
+ * BaseInputOutput io = ...;
+ * if (!BaseIOFolding.isSupported(io)) {
* throw new Exception("Folding is not supported");
* }
* io.getOut().println("First Line - start of fold");
- * FoldHandle fold = IOFolding.startFold(io, true);
+ * BaseFoldHandle fold = BaseIOFolding.startFold(io, true);
* io.getOut().println(" Fold Content 1");
* io.getOut().println(" The first line of nested fold");
- * FoldHandle nestedFold = fold.startFold(true);
+ * BaseFoldHandle nestedFold = fold.startFold(true);
* io.getOut().println(" Nested fold content 1");
* nestedFold.finish();
* io.getOut().println(" Fold Content 2");
@@ -69,88 +68,77 @@
* io.getOut().println("Text outside of the fold.");
*
*
- * How to support {@link IOFolding} in own {@link IOProvider} implementation:
+ * How to support {@link BaseIOFolding} in own {@link BaseIOProvider} implementation:
*
*
- *
{@link InputOutput} provided by {@link IOProvider} has to implement
- * {@link Provider}
- *
Extend {@link IOFolding} and implement its abstract methods
+ *
Implement some {@link Provider} of BaseIOFolding
*
Extend {@link FoldHandleDefinition}
- *
Place instance of {@link IOFolding} to {@link Lookup} provided by
- * {@link InputOutput}
+ *
Place instance of {@link Provider} to {@link Lookup} provided by
+ * {@link BaseInputOutput}
*
*
* @author jhavlin
* @since openide.io/1.38
*/
-public abstract class IOFolding {
+public final class BaseIOFolding {
+
+ private BaseIOFolding() {}
/**
- * Check whether an {@link InputOutput} supports folding.
+ * Check whether an {@link BaseInputOutput} supports folding.
*
- * @param io The InputOutput to check.
- * @return True if {@link #startFold(InputOutput, boolean)} can be used with
- * {@code io}, false otherwise.
+ * @param io The {@link BaseInputOutput} to check.
+ * @return True if {@link #startFold(BaseInputOutput, boolean)} can be used
+ * with {@code io}, false otherwise.
*/
- public static boolean isSupported(@NonNull InputOutput io) {
+ public static boolean isSupported(@NonNull BaseInputOutput io) {
Parameters.notNull("parent", io); //NOI18N
- return findIOFolding(io) != null;
+ return ExtrasHelper.isSupported(io, BaseIOFolding.Provider.class);
}
- /**
- * Find folding support in an {@link InputOutput} object.
- *
- * @return IOFolding object if folding is supported by the {@code parent}
- * object, null otherwise.
- */
- private static IOFolding findIOFolding(InputOutput parent) {
- return (parent instanceof Lookup.Provider)
- ? ((Lookup.Provider) parent).getLookup().lookup(IOFolding.class)
- : null;
+ public interface Provider {
+
+ /**
+ * Create a fold handle definition for the current last line in the
+ * output window.
+ *
+ * @param expanded Initial state of the fold.
+ * @return FoldHandleDefinition for the fold handle. Never null.
+ *
+ * @throws IllegalStateException if the last fold hasn't been finished
+ * yet.
+ */
+ @NonNull
+ FoldHandleDefinition startFold(boolean expanded);
}
/**
- * Create a fold handle definition for the current last line in the output
- * window.
- *
- * @param expanded Initial state of the fold.
- * @return FoldHandleDefinition for the fold handle. Never null.
- *
- * @throws IllegalStateException if the last fold hasn't been finished yet.
- */
- @NonNull
- protected abstract FoldHandleDefinition startFold(boolean expanded);
-
- /**
* Create a fold handle for the current last line in the output window.
*
- * @param io InputOutput to create the fold in.
+ * @param io {@link BaseInputOutput} to create the fold in.
* @param expanded Initial state of the fold.
* @return The fold handle that can be used to finish the fold or to create
* nested folds.
* @throws IllegalStateException if the last fold hasn't been finished yet.
* @throws UnsupportedOperationException if folding is not supported by the
- * InputOutput object.
+ * {@link BaseInputOutput} object.
*/
@CheckReturnValue
@NonNull
- public static FoldHandle startFold(
- @NonNull InputOutput io, boolean expanded) {
+ public static BaseFoldHandle startFold(
+ @NonNull BaseInputOutput io, boolean expanded) {
Parameters.notNull("io", io); //NOI18N
- IOFolding folding = findIOFolding(io);
- if (folding == null) {
- throw new UnsupportedOperationException(
- "The InputOutput doesn't support folding"); //NOI18N
- } else {
- return new FoldHandle(folding.startFold(expanded));
- }
+ BaseIOFolding.Provider folding = ExtrasHelper.getExtras(io,
+ BaseIOFolding.Provider.class);
+
+ return new BaseFoldHandle(folding.startFold(expanded));
}
/**
* An SPI for creating custom FoldHandle implementations.
*/
- protected static abstract class FoldHandleDefinition {
+ public interface FoldHandleDefinition {
/**
* Finish the fold at the current last line. Ensure that nested folds
@@ -159,7 +147,7 @@
* @throws IllegalStateException if parent fold has been already
* finished, or if there is an unfinished nested fold.
*/
- public abstract void finish();
+ public void finish();
/**
* Start a new fold at the current last line. Ensure that the parent
@@ -171,7 +159,7 @@
* @throws IllegalStateException if the fold has been already finished,
* or if the last nested fold hasn't been finished yet.
*/
- public abstract FoldHandleDefinition startFold(boolean expanded);
+ public FoldHandleDefinition startFold(boolean expanded);
/**
* Set state of the fold.
@@ -180,6 +168,6 @@
*
* @param expanded True to expand the fold, false to collapse it.
*/
- public abstract void setExpanded(boolean expanded);
+ public void setExpanded(boolean expanded);
}
}
diff --git a/openide.io.base/src/org/openide/io/base/BaseIOHyperlink.java b/openide.io.base/src/org/openide/io/base/BaseIOHyperlink.java
new file mode 100644
--- /dev/null
+++ b/openide.io.base/src/org/openide/io/base/BaseIOHyperlink.java
@@ -0,0 +1,201 @@
+/*
+ * 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.io.base;
+
+import java.io.IOException;
+import org.netbeans.api.annotations.common.NonNull;
+import org.openide.util.Lookup;
+
+/**
+ * Text printing with listeners, tags, or custom extension types.
+ *
+ *
+ * Client usage:
+ *
+ *
+ BaseInputOutput io = ...;
+ BaseOutputListener l = ...;
+ BaseOutputTag t = ...;
+
+ // check only one extension type
+ if (BaseIOHyperlink.isSupported(io, BaseOutputListener.class) {
+ BaseIOHyperlink.println(io, "Link", false, l);
+ }
+
+ // to print a single line with several extensions
+ if (BaseIOHyperlink.isSupported(io)) { //check extensions supported at all
+ List<Object> exts = new LinkedList<Object>();
+ if (BaseIOHyperlink.isSupported(io, BaseOutputListener.class)) {
+ exts.add(new MyOutputListener());
+ }
+ if (BaseIOHyperlink.isSupported(io, BaseOutputTag.class)) {
+ exts.add(new MyOutputTag());
+ }
+ BaseIOHyperlink.println(io, "Link 2", false, exts.toArray(new Object[exts.size()]));
+ }
+
+
+ * How to support {@link BaseIOHyperlink} in own {@link BaseIOProvider} implementation:
+ *
+ *
Implement some {@link Provider} of BaseIOHyperlink.
+ *
Place instance of {@link Provider} to {@link Lookup} provided by {@link BaseInputOutput}.
+ *
+ *
+ * @author Jaroslav Havlin
+ */
+public final class BaseIOHyperlink {
+
+ private BaseIOHyperlink() {}
+
+ public enum Type {
+
+ OUT, ERR;
+ }
+
+ /**
+ * Check whether BaseIOHyperlink extension is supported by the I/O.
+ *
+ * @param io The I/O to check for support of BaseIOHyperlink.
+ * @return True if BaseIOHyperlink is supported by the I/O, false otherwise.
+ */
+ public static boolean isSupported(@NonNull BaseInputOutput io) {
+ return ExtrasHelper.isSupported(io, BaseIOHyperlink.Provider.class);
+ }
+
+ /**
+ * Print a line which will be displayed as a hyperlink, calling the action
+ * specified in the array object if it is clicked.
+ *
+ * @param io I/O to print into.
+ * @param type Type of output, standard or error.
+ * @param str a string to print to the tab
+ * @param important mark the line as important. Makes the UI respond
+ * appropriately, eg. stop the automatic scrolling or highlight the
+ * hyperlink.
+ * @param linkInfo array containing extending info for the text, e.g.
+ * an output listener and/or an output tag.
+ * @throws IOException if the string could not be printed
+ * @throws IllegalArgumentException if the I/O does not support this feature.
+ */
+ public static void println(
+ @NonNull BaseInputOutput io,
+ @NonNull Type type,
+ @NonNull String str,
+ boolean important,
+ @NonNull BaseIOLinkInfo... linkInfo) throws IOException {
+ ExtrasHelper.getExtras(io, BaseIOHyperlink.Provider.class).println(
+ type, str, important, linkInfo);
+ }
+
+ /**
+ * Print a line which will be displayed as a hyperlink, calling the action
+ * specifided in the {@link Lookup} object if it is clicked, if the caret
+ * enters it, or if the enter key is pressed over it.
+ *
+ * @param io I/O to print into.
+ * @param type Type of output, standard or error.
+ * @param str a string to print to the tab
+ * @param linkInfo array containing extending info for the text, e.g.
+ * an output listener and/or an output tag.
+ * @throws IOException if the string could not be printed
+ * @throws IllegalArgumentException if the I/O does not support this feature.
+ */
+ public static void println(
+ @NonNull BaseInputOutput io,
+ @NonNull Type type,
+ @NonNull String str,
+ @NonNull BaseIOLinkInfo... linkInfo) throws IOException {
+ println(io, type, str, false, linkInfo);
+ }
+
+ /**
+ * Check whether BaseIOHyperlink is supported by the I/O and that its lines
+ * can be extended with link info of class {@code cls}.
+ *
+ * @param io I/O object to get extending types from.
+ * @param cls The link info class that we want to check the support for.
+ * @return True if the I/O supports {@link BaseIOHyperlink} and if it can be
+ * extended with instances of class {@code cls}.
+ */
+ public static boolean isSupported(
+ @NonNull BaseInputOutput io,
+ @NonNull Class extends BaseIOLinkInfo> cls) {
+ Provider p = ExtrasHelper.find(io, Provider.class);
+ return p == null
+ ? false
+ : p.isSupported(cls);
+ }
+
+ /**
+ * SPI for implementing support for {@link BaseIOHyperlink}.
+ */
+ public interface Provider {
+
+ /**
+ * Check whether passed class or interface is supported by this
+ * implementation of BaseOutputWriter and can be put to the array passed
+ * to
+ * {@link #println(BaseIOHyperlink.Type, String, boolean, BaseIOLinkInfo...)}.
+ *
+ * @param cls Class or interface to check
+ * @return True if class or interface {@code cls} is supported.
+ */
+ boolean isSupported(@NonNull Class extends BaseIOLinkInfo> cls);
+
+ /**
+ * Print a line which will be displayed as a hyperlink, calling the
+ * action specifided in the array object if it is clicked.
+ *
+ * @param type Type of the output, {@link Type#OUT} for standard output,
+ * {@link Type#ERR} for error output.
+ * @param s a string to print to the tab
+ * @param linkInfo array containing extending info for the text,
+ * e.g. an output listener and/or an output tag.
+ * @param important mark the line as important. Makes the UI respond
+ * appropriately, eg. stop the automatic scrolling or highlight the
+ * hyperlink.
+ * @throws IOException if the string could not be printed.
+ */
+ void println(@NonNull Type type, @NonNull String s, boolean important,
+ @NonNull BaseIOLinkInfo... linkInfo) throws IOException;
+ }
+}
diff --git a/openide.io.base/src/org/openide/io/base/BaseIOLinkInfo.java b/openide.io.base/src/org/openide/io/base/BaseIOLinkInfo.java
new file mode 100644
--- /dev/null
+++ b/openide.io.base/src/org/openide/io/base/BaseIOLinkInfo.java
@@ -0,0 +1,51 @@
+/*
+ * 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.io.base;
+
+/**
+ * Marker interface for classes that can be used as extending link info for
+ * {@link BaseIOHyperlink}.
+ *
+ * @author jhavlin
+ */
+public interface BaseIOLinkInfo {
+}
diff --git a/openide.io/src/org/openide/windows/IOPosition.java b/openide.io.base/src/org/openide/io/base/BaseIOPosition.java
copy from openide.io/src/org/openide/windows/IOPosition.java
copy to openide.io.base/src/org/openide/io/base/BaseIOPosition.java
--- a/openide.io/src/org/openide/windows/IOPosition.java
+++ b/openide.io.base/src/org/openide/io/base/BaseIOPosition.java
@@ -40,40 +40,37 @@
* Portions Copyrighted 2008 Sun Microsystems, Inc.
*/
-package org.openide.windows;
+package org.openide.io.base;
+import org.netbeans.api.annotations.common.CheckForNull;
+import org.netbeans.api.annotations.common.NonNull;
import org.openide.util.Lookup;
/**
* Navigation (scrolling) in IO component.
- *
+ *
* Client usage:
+ *
*
- * InputOutput io = ...;
- * // store current position of IO
- * IOPosition.Position pos = IOPosition.currentPosition(io);
- * ...
- * // scroll to stored position
- * pos.scrollTo();
- *
- * How to support {@link IOPosition} in own {@link IOProvider} implementation:
+ BaseInputOutput io = ...;
+ // store current position of IO
+ Position pos = BaseIOPosition.currentPosition(io);
+ ...
+ // scroll to stored position
+ pos.scrollTo();
+ How to support {@link BaseIOPosition} in own {@link BaseIOProvider}
+ * implementation:
*
- *
{@link InputOutput} provided by {@link IOProvider} has to implement {@link org.openide.util.Lookup.Provider}
- *
Extend {@link IOPosition} and implement its abstract methods
- *
Place instance of {@link IOPosition} to {@link Lookup} provided by {@link InputOutput}
+ *
Implement {@link Provider} and implement its methods.
+ *
Place instance of {@link Provider} to {@link Lookup} provided by
+ * {@link BaseInputOutput}
*
- * @since 1.16
- * @author Tomas Holy
+ *
+ * @author Tomas Holy, Jaroslav Havlin
*/
-public abstract class IOPosition {
+public final class BaseIOPosition {
- private static IOPosition find(InputOutput io) {
- if (io instanceof Lookup.Provider) {
- Lookup.Provider p = (Lookup.Provider) io;
- return p.getLookup().lookup(IOPosition.class);
- }
- return null;
- }
+ private BaseIOPosition() {}
public interface Position {
void scrollTo();
@@ -81,11 +78,13 @@
/**
* Gets current position (in number of chars) in IO
- * @param io IO to operate on
- * @return current position or null if not supported
+ * @param io IO to operate on.
+ * @return Current position or null if not supported.
*/
- public static Position currentPosition(InputOutput io) {
- IOPosition iop = find(io);
+ public static @CheckForNull Position currentPosition(
+ @NonNull BaseInputOutput io) {
+
+ Provider iop = ExtrasHelper.find(io, Provider.class);
return iop != null ? iop.currentPosition() : null;
}
@@ -94,13 +93,17 @@
* @param io IO to check on
* @return true if supported
*/
- public static boolean isSupported(InputOutput io) {
- return find(io) != null;
+ public static boolean isSupported(BaseInputOutput io) {
+ return ExtrasHelper.isSupported(io, Provider.class);
}
- /**
- * Gets current position in IO
- * @return current position
- */
- abstract protected Position currentPosition();
+ public interface Provider {
+
+ /**
+ * Gets current position in IO
+ *
+ * @return current position
+ */
+ Position currentPosition();
+ }
}
diff --git a/openide.io.base/src/org/openide/io/base/BaseIOProvider.java b/openide.io.base/src/org/openide/io/base/BaseIOProvider.java
new file mode 100644
--- /dev/null
+++ b/openide.io.base/src/org/openide/io/base/BaseIOProvider.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.openide.io.base;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.util.Collection;
+import java.util.EventListener;
+import org.netbeans.api.annotations.common.NonNull;
+import org.openide.util.Lookup;
+
+/**
+ * A factory for IO tabs. To create a new tab to write to, call e.g.
+ * BaseIOProvider.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).
+ *
+ * @author jhavlin
+ */
+public abstract class BaseIOProvider {
+
+ public static @NonNull BaseIOProvider getDefault() {
+ BaseIOProvider iopb = Lookup.getDefault().lookup(BaseIOProvider.class);
+ if (iopb == null) {
+ iopb = new Trivial();
+ }
+ return iopb;
+ }
+
+ /**
+ * Gets BaseIOProvider of selected name or delegates to getDefault() if none
+ * was found.
+ *
+ * @param name ID of provider.
+ * @return The instance corresponding to provided name or default instance
+ * if not found.
+ */
+ public static @NonNull BaseIOProvider get(@NonNull String name) {
+ Collection extends BaseIOProvider> res = Lookup.getDefault().lookupAll(
+ BaseIOProvider.class);
+ for (BaseIOProvider iop : res) {
+ if (iop.getName().equals(name)) {
+ return iop;
+ }
+ }
+ return getDefault();
+ }
+
+ /**
+ * Gets name (ID) of provider
+ *
+ * @return name of provider
+ */
+ public abstract @NonNull String getName();
+
+ /**
+ * Get a named instance of {@link BaseInputOutput}, 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 {@link BaseInputOutput} is returned,
+ * else an existing {@link BaseInputOutput} of the same name may be
+ * returned.
+ * @param actions Objects that specify actions available in the I/O tab,
+ * usually {@link javax.swing.Action} instances, possibly
+ * {@link BaseOutputTag} instances, depending on what the BaseIOProvider
+ * supports.
+ * @return An {@link BaseInputOutput} instance for accessing the new tab.
+ * @see BaseInputOutput
+ */
+ public abstract @NonNull
+ BaseInputOutput getIO(
+ @NonNull String name, boolean newIO, EventListener... actions);
+
+ /**
+ * Check whether this implementation supports action type {@code cls}.
+ *
+ * @param cls Action type to check the support for.
+ *
+ * @return True if the passed type can be used for specifying actions for
+ * the output tab, false if the passed type is not supported.
+ *
+ * @see #getIO(java.lang.String, boolean, java.util.EventListener...)
+ */
+ public abstract boolean isActionTypeSupported(
+ @NonNull Class extends EventListener> cls);
+
+ /**
+ * Fallback implementation.
+ */
+ private static final class Trivial extends BaseIOProvider {
+
+ private static final Reader in = new BufferedReader(
+ new InputStreamReader(System.in));
+ private static final PrintStream out = System.out;
+ private static final PrintStream err = System.err;
+
+ public Trivial() {
+ }
+
+ @Override
+ public String getName() {
+ return "Trivial"; //NOI18N
+ }
+
+ @Override
+ public BaseInputOutput getIO(String name, boolean newIO,
+ EventListener... actions) {
+ return new TrivialIO(name);
+ }
+
+ @Override
+ public boolean isActionTypeSupported(
+ Class extends EventListener> cls) {
+ return false;
+ }
+
+ @SuppressWarnings("deprecation")
+ private final class TrivialIO implements BaseInputOutput {
+
+ private final String name;
+
+ public TrivialIO(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public Reader getIn() {
+ return in;
+ }
+
+ @Override
+ public PrintWriter getOut() {
+ return new TrivialOW(out, name);
+ }
+
+ @Override
+ public PrintWriter getErr() {
+ return new TrivialOW(err, name);
+ }
+
+ public Reader flushReader() {
+ return getIn();
+ }
+
+ @Override
+ public boolean isClosed() {
+ return false;
+ }
+
+ @Override
+ public void closeInputOutput() {
+ }
+
+ @Override
+ public void reset() {
+ }
+
+ @Override
+ public Lookup getLookup() {
+ return Lookup.EMPTY;
+ }
+ }
+
+ private static final class TrivialOW extends PrintWriter {
+
+ private static int count = 0;
+ private final String name;
+ private final PrintStream stream;
+
+ @SuppressWarnings("ValueOfIncrementOrDecrementUsed")
+ public TrivialOW(PrintStream stream, String name) {
+ // XXX using super(new PrintWriter(stream)) does not seem to work for some reason!
+ super(new StringWriter());
+ this.stream = stream;
+ if (name != null) {
+ this.name = name;
+ } else {
+ this.name = "anon-" + ++count; // NOI18N
+ }
+ }
+
+ private void prefix(boolean hyperlink) {
+ if (hyperlink) {
+ stream.print("[" + name + "]* "); // NOI18N
+ } else {
+ stream.print("[" + name + "] "); // NOI18N
+ }
+ }
+
+ @Override
+ public void println(float x) {
+ prefix(false);
+ stream.println(x);
+ }
+
+ @Override
+ public void println(double x) {
+ prefix(false);
+ stream.println(x);
+ }
+
+ @Override
+ public void println() {
+ prefix(false);
+ stream.println();
+ }
+
+ @Override
+ public void println(Object x) {
+ prefix(false);
+ stream.println(x);
+ }
+
+ @Override
+ public void println(int x) {
+ prefix(false);
+ stream.println(x);
+ }
+
+ @Override
+ public void println(char x) {
+ prefix(false);
+ stream.println(x);
+ }
+
+ @Override
+ public void println(long x) {
+ prefix(false);
+ stream.println(x);
+ }
+
+ @Override
+ @SuppressWarnings("ImplicitArrayToString")
+ public void println(char[] x) {
+ prefix(false);
+ stream.println(x);
+ }
+
+ @Override
+ public void println(boolean x) {
+ prefix(false);
+ stream.println(x);
+ }
+
+ @Override
+ public void println(String x) {
+ prefix(false);
+ stream.println(x);
+ }
+
+ @Override
+ public void write(int c) {
+ stream.write(c);
+ }
+
+ @Override
+ public void write(char[] buf, int off, int len) {
+ String s = new String(buf, off, len);
+ if (s.endsWith("\n")) {
+ println(s.substring(0, s.length() - 1));
+ } else {
+ try {
+ stream.write(s.getBytes());
+ } catch (IOException x) {
+ }
+ }
+ }
+
+ @Override
+ public void write(String s, int off, int len) {
+ String sub = s.substring(off, off + len);
+ if (sub.endsWith("\n")) {
+ println(sub.substring(0, sub.length() - 1));
+ } else {
+ try {
+ stream.write(sub.getBytes());
+ } catch (IOException x) {
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/openide.io/src/org/openide/windows/IOSelect.java b/openide.io.base/src/org/openide/io/base/BaseIOSelect.java
copy from openide.io/src/org/openide/windows/IOSelect.java
copy to openide.io.base/src/org/openide/io/base/BaseIOSelect.java
--- a/openide.io/src/org/openide/windows/IOSelect.java
+++ b/openide.io.base/src/org/openide/io/base/BaseIOSelect.java
@@ -40,74 +40,70 @@
* Portions Copyrighted 2010 Sun Microsystems, Inc.
*/
-package org.openide.windows;
+package org.openide.io.base;
import java.util.Set;
-import org.openide.util.Lookup;
+import org.netbeans.api.annotations.common.NonNull;
import org.openide.util.Parameters;
/**
- * Capability of an InputOutput of finer grained selection of a component.
- *
- * InputOutput.select() does too much.
- * @author ivan
- * @since 1.23
+ * Capability of an {@link BaseInputOutput} of fine grained selection of a
+ * component.
+ *
+ * @author ivan, Jaroslav Havlin
*/
-public abstract class IOSelect {
+public final class BaseIOSelect {
+
+ private BaseIOSelect() {}
/**
- * Additional operations to perform when issuing {@link IOSelect#select}.
+ * Additional operations to perform when selecting the output tab.
* @author ivan
*/
public static enum AdditionalOperation {
- /**
- * Additionally issue open() on the TopComponent containing the InputOutput.
- */
+ /**
+ * Additionally issue open() on the TopComponent containing the
+ * {@link BaseInputOutput}.
+ */
OPEN,
/**
- * Additionally issue requestVisible() on the TopComponent containing the InputOutput.
+ * Additionally issue requestVisible() on the TopComponent containing
+ * the {@link BaseInputOutput}.
*/
REQUEST_VISIBLE,
/**
- * Additionally issue requestActive() on the TopComponent containing the InputOutput.
+ * Additionally issue requestActive() on the TopComponent containing
+ * the {@link BaseInputOutput}.
*/
REQUEST_ACTIVE
}
- private static IOSelect find(InputOutput io) {
- if (io instanceof Lookup.Provider) {
- Lookup.Provider p = (Lookup.Provider) io;
- return p.getLookup().lookup(IOSelect.class);
- }
- return null;
- }
-
/**
* With an empty 'extraOps' simply selects this io
* without involving it's containing TopComponent.
*
- * If this capability is not supported then regular InputOutput.select()
- * will be called.
- * @param io InputOutput to operate on.
+ * If this capability is not supported then no operation will be performed.
+ *
+ * @param io {@link BaseInputOutput} to operate on.
* @param extraOps Additional operations to apply to the containing
* TopComponent.
*/
- public static void select(InputOutput io, Set extraOps) {
+ public static void select(BaseInputOutput io, Set extraOps) {
Parameters.notNull("extraOps", extraOps); // NOI18N
- IOSelect ios = find(io);
- if (ios != null)
- ios.select(extraOps);
- else
- io.select(); // fallback
+ Provider ios = ExtrasHelper.find(io, Provider.class);
+ if (ios != null) {
+ ios.select(extraOps);
+ }
}
/**
@@ -115,15 +111,19 @@
* @param io IO to check on
* @return true if supported
*/
- public static boolean isSupported(InputOutput io) {
- return find(io) != null;
+ public static boolean isSupported(BaseInputOutput io) {
+ return ExtrasHelper.isSupported(io, Provider.class);
}
- /**
- * With an empty 'extraOps' simply selects this io
- * without involving it's containing TopComponent.
- * @param extraOps Additional operations to apply to the containing
- * TopComponent.
- */
- abstract protected void select(Set extraOps);
+ public interface Provider {
+
+ /**
+ * With an empty 'extraOps' simply selects this io without involving
+ * it's containing TopComponent.
+ *
+ * @param extraOps Additional operations to apply to the containing
+ * TopComponent.
+ */
+ void select(@NonNull Set extraOps);
+ }
}
diff --git a/openide.io/src/org/openide/windows/IOTab.java b/openide.io.base/src/org/openide/io/base/BaseIOTab.java
copy from openide.io/src/org/openide/windows/IOTab.java
copy to openide.io.base/src/org/openide/io/base/BaseIOTab.java
--- a/openide.io/src/org/openide/windows/IOTab.java
+++ b/openide.io.base/src/org/openide/io/base/BaseIOTab.java
@@ -40,9 +40,11 @@
* Portions Copyrighted 2008 Sun Microsystems, Inc.
*/
-package org.openide.windows;
+package org.openide.io.base;
-import javax.swing.Icon;
+import org.netbeans.api.annotations.common.CheckForNull;
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.api.annotations.common.NullAllowed;
import org.openide.util.Lookup;
/**
@@ -51,68 +53,41 @@
* Client usage:
*
- * How to support {@link IOTab} in own {@link IOProvider} implementation:
+ * How to support {@link BaseIOTab} in own {@link BaseIOProvider} implementation:
*
- *
{@link InputOutput} provided by {@link IOProvider} has to implement {@link org.openide.util.Lookup.Provider}
- *
Extend {@link IOTab} and implement its abstract methods
- *
Place instance of {@link IOTab} to {@link Lookup} provided by {@link InputOutput}
+ *
Implement {@link Provider}.
+ *
Place instance of {@link Provider} to {@link Lookup} provided by {@link BaseInputOutput}.
*
- * @since 1.15
- * @author Tomas Holy
+ * @author Tomas Holy, Jaroslav Havlin
*/
-public abstract class IOTab {
- private static IOTab find(InputOutput io) {
- if (io instanceof Lookup.Provider) {
- Lookup.Provider p = (Lookup.Provider) io;
- return p.getLookup().lookup(IOTab.class);
- }
- return null;
- }
+public final class BaseIOTab {
- /**
- * Gets current tab icon for specified IO
- * @param io IO to operate on
- * @return current tab icon or null if not supported
- */
- public static Icon getIcon(InputOutput io) {
- IOTab iot = find(io);
- return iot != null ? iot.getIcon() : null;
- }
-
- /**
- * Sets icon to tab corresponding to specified IO
- * @param io IO to operate on
- * @param icon tab icon
- */
- public static void setIcon(InputOutput io, Icon icon) {
- IOTab iot = find(io);
- if (iot != null) {
- iot.setIcon(icon);
- }
- }
+ private BaseIOTab() {}
/**
* Gets current tool tip text for specified IO
- * @param io IO to operate on
- * @return current tool tip text or null if not supported
+ * @param io IO to operate on.
+ * @return Current tool tip text or null if not supported.
*/
- public static String getToolTipText(InputOutput io) {
- IOTab iot = find(io);
+ public static @CheckForNull String getToolTipText(
+ @NonNull BaseInputOutput io) {
+
+ Provider iot = ExtrasHelper.find(io, Provider.class);
return iot != null ? iot.getToolTipText() : null;
}
/**
* Sets tool tip text to tab corresponding to specified IO
- * @param io IO to operate on
- * @param text new tool tip text
+ * @param io IO to operate on.
+ * @param text New tool tip text.
*/
- public static void setToolTipText(InputOutput io, String text) {
- IOTab iot = find(io);
+ public static void setToolTipText(
+ @NonNull BaseInputOutput io,
+ @NullAllowed String text) {
+ Provider iot = ExtrasHelper.find(io, Provider.class);
if (iot != null) {
iot.setToolTipText(text);
}
@@ -120,35 +95,30 @@
/**
* Checks whether this feature is supported for provided IO
- * @param io IO to check on
- * @return true if supported
+ * @param io IO to check on.
+ * @return True if supported.
*/
- public static boolean isSupported(InputOutput io) {
- return find(io) != null;
+ public static boolean isSupported(BaseInputOutput io) {
+ return ExtrasHelper.isSupported(io, Provider.class);
}
/**
- * Gets current tab icon
- * @return current tab icon
+ * SPI for implementation of {@link BaseIOTab} support.
*/
- abstract protected Icon getIcon();
+ public interface Provider {
+ /**
+ * Gets current tool tip text.
+ *
+ * @return Current tool tip text.
+ */
+ @CheckForNull String getToolTipText();
- /**
- * Sets icon to tab
- * @param icon tab icon
- */
- abstract protected void setIcon(Icon icon);
-
- /**
- * Gets current tool tip text
- * @return current tool tip text
- */
- abstract protected String getToolTipText();
-
- /**
- * Sets tool tip text to tab
- * @param text new tool tip text
- */
- abstract protected void setToolTipText(String text);
+ /**
+ * Sets tool tip text to tab.
+ *
+ * @param text New tool tip text.
+ */
+ void setToolTipText(@NullAllowed String text);
+ }
}
diff --git a/openide.io.base/src/org/openide/io/base/BaseInputOutput.java b/openide.io.base/src/org/openide/io/base/BaseInputOutput.java
new file mode 100644
--- /dev/null
+++ b/openide.io.base/src/org/openide/io/base/BaseInputOutput.java
@@ -0,0 +1,112 @@
+/*
+ * 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.io.base;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Reader;
+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.,
+ * BaseIOProvider.getDefault().getIO("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.openide.io.base.BaseInputOutput}, but rather to fetch it by name
+ * from {@link org.openide.io.base.BaseIOProvider} as needed.
+ *
+ *
+ * @author Ian Formanek, Jaroslav Tulach, Petr Hamernik, Ales Novak, Jan
+ * Jancura, Jaroslav Havlin
+ */
+public interface BaseInputOutput extends Lookup.Provider {
+
+ /**
+ * Acquire an output writer to write to the tab. This is the usual use of a
+ * tab--it writes to the main output pane.
+ *
+ * @return the writer
+ */
+ public PrintWriter getOut();
+
+ /**
+ * Get a reader to read from the tab. If a reader is ever requested, an
+ * input line is added to the tab and used to read one line at a time.
+ *
+ * @return the reader
+ */
+ public Reader getIn();
+
+ /**
+ * 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
+ */
+ public PrintWriter getErr();
+
+ /**
+ * Closes this tab. The effect of calling any method on an instance of
+ * {@link BaseInputOutput} after calling {@link #closeInputOutput()} on it
+ * is undefined.
+ */
+ public void closeInputOutput();
+
+ /**
+ * Test whether this tab has been closed, either by a call to
+ * closeInputOutput() or by the user closing the tab in the UI.
+ *
+ * @see #closeInputOutput
+ * @return true if it is closed
+ */
+ public boolean isClosed();
+
+ /**
+ * Clean the output area.
+ * @throws java.io.IOException
+ */
+ void reset() throws IOException;
+}
diff --git a/openide.io.base/src/org/openide/io/base/BaseOutputEvent.java b/openide.io.base/src/org/openide/io/base/BaseOutputEvent.java
new file mode 100644
--- /dev/null
+++ b/openide.io.base/src/org/openide/io/base/BaseOutputEvent.java
@@ -0,0 +1,70 @@
+/*
+ * 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.io.base;
+
+/**
+ * Event fired when something happens to a line in the Output Window.
+ *
+ * @author Jaroslav Tulach, Petr Hamernik, Jaroslav Havlin
+ */
+public abstract class BaseOutputEvent extends java.util.EventObject {
+ /** generated Serialized Version UID */
+ static final long serialVersionUID = 4809584286971828815L;
+ /** Create an event.
+ * @param src the tab in question
+ */
+ public BaseOutputEvent (BaseInputOutput src) {
+ super (src);
+ }
+
+ /** Get the text on the line.
+ * @return the text
+ */
+ public abstract String getLine ();
+
+ /** Get the Output Window tab in question.
+ * @return the tab
+ */
+ public BaseInputOutput getInputOutput() {
+ return (BaseInputOutput) getSource();
+ }
+}
diff --git a/openide.io.base/src/org/openide/io/base/BaseOutputListener.java b/openide.io.base/src/org/openide/io/base/BaseOutputListener.java
new file mode 100644
--- /dev/null
+++ b/openide.io.base/src/org/openide/io/base/BaseOutputListener.java
@@ -0,0 +1,59 @@
+/*
+ * 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.io.base;
+
+/**
+ * Listener to actions taken on a line in the Output Window.
+ *
+ * @author Jaroslav Tulach
+ * @version 0.11 Dec 01, 1997
+ */
+public interface BaseOutputListener extends java.util.EventListener,
+ BaseIOLinkInfo {
+
+ /**
+ * Called when some sort of action is performed on a line.
+ *
+ * @param ev the event describing the line
+ */
+ void outputLineAction(BaseOutputEvent ev);
+}
diff --git a/openide.io.base/src/org/openide/io/base/BaseOutputTag.java b/openide.io.base/src/org/openide/io/base/BaseOutputTag.java
new file mode 100644
--- /dev/null
+++ b/openide.io.base/src/org/openide/io/base/BaseOutputTag.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.openide.io.base;
+
+import java.util.EventListener;
+import java.util.Set;
+
+/**
+ * Base class for adding tagging information to output text.
+ *
+ * @author jhavlin
+ */
+public interface BaseOutputTag extends BaseIOLinkInfo, EventListener {
+
+ /**
+ * Get type of this tag.
+ *
+ * @return Type of the tag.
+ */
+ String getType();
+
+ /**
+ * Get value of an attribute specified by name.
+ *
+ * @param attributeName Name of the attribute.
+ * @return Value of the attribute, or null if it is not available.
+ * @throws IllegalArgumentException If tag of this type should not be
+ * queried for attribute of name {@code attributeName}.
+ */
+ Object getAttribute(String attributeName);
+
+ /**
+ * Get set of names of available attributes.
+ *
+ * @return Set of attribute names.
+ */
+ Set getAttributeNames();
+}
diff --git a/openide.io.base/src/org/openide/io/base/Bundle.properties b/openide.io.base/src/org/openide/io/base/Bundle.properties
new file mode 100644
--- /dev/null
+++ b/openide.io.base/src/org/openide/io/base/Bundle.properties
@@ -0,0 +1,1 @@
+OpenIDE-Module-Name=Base I/O APIs
diff --git a/openide.io.base/src/org/openide/io/base/ExtrasHelper.java b/openide.io.base/src/org/openide/io/base/ExtrasHelper.java
new file mode 100644
--- /dev/null
+++ b/openide.io.base/src/org/openide/io/base/ExtrasHelper.java
@@ -0,0 +1,100 @@
+/*
+ * 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.io.base;
+
+/**
+ * Helper class for finding extensions in I/O's lookup.
+ *
+ * @author jhavlin
+ */
+class ExtrasHelper {
+
+ private ExtrasHelper() {}
+
+ /**
+ * Check whether class {@code extras} is present in the I/O's lookup.
+ *
+ * @param io I/O to check
+ * @param extras Extension class that should be supported.
+ *
+ * @return True if the I/O supports the extension class, false otherwise.
+ */
+ static boolean isSupported(BaseInputOutput io, Class> extras) {
+ Object o = io.getLookup().lookup(extras);
+ return o != null;
+ }
+
+ /**
+ * Get extension of given type, or throw an exception if it is not present.
+ *
+ * @param Type of the extension.
+ * @param io I/O to get the extension for.
+ * @param cls Extension class.
+ *
+ * @return The extension object of given type.
+ * @throws IllegalArgumentException If the I/O does not support this
+ * extension type.
+ */
+ static T getExtras(BaseInputOutput io, Class cls) {
+ T extras = io.getLookup().lookup(cls);
+ if (extras == null) {
+ throw new IllegalArgumentException("BaseInputOutput " + io
+ + " does not support " + cls);
+ } else {
+ return extras;
+ }
+ }
+
+ /**
+ * Get extension of given type, or return null if it is not present.
+ *
+ * @param Type of the extension.
+ * @param io I/O to get the extension for.
+ * @param cls Extension class.
+ *
+ * @return The extension object of given type, or null if it is not
+ * supported.
+ */
+ static T find(BaseInputOutput io, Class cls) {
+ return io.getLookup().lookup(cls);
+ }
+}