ClipboardStream.java
/*
** Module : ClipboardStream.java
** Abstract : Implements the output stream to write data into the client's system clipboard.
**
** Copyright (c) 2018-2024, Golden Code Development Corporation.
**
** -#- -I- --Date-- --------------------------------Description-----------------------------------
** 001 SBI 20180213 Created the output stream to write strings data into the system clipboard.
** 002 EVL 20220325 Base refactoring for Stream based classes getting single byte and array of bytes.
** 003 GBB 20240912 UnsupportedOperationException on launching with server-side streams.
*/
/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 of the
** License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
**
** Additional terms under GNU Affero GPL version 3 section 7:
**
** Under Section 7 of the GNU Affero GPL version 3, the following additional
** terms apply to the works covered under the License. These additional terms
** are non-permissive additional terms allowed under Section 7 of the GNU
** Affero GPL version 3 and may not be removed by you.
**
** 0. Attribution Requirement.
**
** You must preserve all legal notices or author attributions in the covered
** work or Appropriate Legal Notices displayed by works containing the covered
** work. You may not remove from the covered work any author or developer
** credit already included within the covered work.
**
** 1. No License To Use Trademarks.
**
** This license does not grant any license or rights to use the trademarks
** Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
** of Golden Code Development Corporation. You are not authorized to use the
** name Golden Code, FWD, or the names of any author or contributor, for
** publicity purposes without written authorization.
**
** 2. No Misrepresentation of Affiliation.
**
** You may not represent yourself as Golden Code Development Corporation or FWD.
**
** You may not represent yourself for publicity purposes as associated with
** Golden Code Development Corporation, FWD, or any author or contributor to
** the covered work, without written authorization.
**
** 3. No Misrepresentation of Source or Origin.
**
** You may not represent the covered work as solely your work. All modified
** versions of the covered work must be marked in a reasonable way to make it
** clear that the modified work is not originating from Golden Code Development
** Corporation or FWD. All modified versions must contain the notices of
** attribution required in this license.
*/
package com.goldencode.p2j.util;
import java.io.*;
import java.nio.charset.*;
import com.goldencode.p2j.ui.chui.*;
import com.goldencode.p2j.util.osresource.*;
/**
* Implements the output stream into the client's system clipboard. The actual string data are
* written into the system clipboard on closing this stream.
*/
class ClipboardStream
extends Stream
{
/** The default buffer size */
private static int BUFFER_SIZE = 65536;
/** The default charset */
private final Charset charset;
/**
* The intermediate buffer for writing data into this stream.
*/
private final ByteArrayOutputStream buffer;
/** Character stream encoder */
private final OutputStreamWriter writer;
/**
* Creates this instance.
*/
public ClipboardStream()
{
buffer = new ByteArrayOutputStream(BUFFER_SIZE);
charset = Charset.defaultCharset();
writer = new OutputStreamWriter(buffer, charset);
}
/**
* The number of bytes available to be immediately read without blocking.
*
* @return The number of available bytes.
*
* @throws IOException
* if an I/O error occurs.
*/
@Override
public long available()
throws IOException
{
throw new UnsupportedOperationException();
}
/**
* The 0-based offset into the stream at which the next read or write will
* occur. This does not work for "streams" that require sequential
* access.
*
* @return The current position in the stream.
*
* @throws UnsupportedOperationException
* If the requested operation is not supported.
* @throws IOException
* If an I/O error occurs.
*/
@Override
public long getPos()
throws UnsupportedOperationException,
IOException
{
throw new UnsupportedOperationException();
}
/**
* Moves the current read/write position to the specified absolute 0-based
* offset. A negative offset is ignored (no action is taken). If the
* specified offset is larger than the length of the stream, the seek
* position will report as the number requested, but if no subsequent
* writes occur to the file, the file is truncated to 0 bytes. If writes
* do occur, all writes occur at byte 0 BUT the file actually is of a size
* that is the requested offset + the number of bytes written!
* <p>
* This does not work for "streams" that require sequential access.
*
* @param pos
* The new read/write position in the stream.
*
* @throws UnsupportedOperationException
* If the requested operation is not supported.
* @throws IOException
* If an I/O error occurs.
*/
@Override
public void setPos(long pos)
throws UnsupportedOperationException,
IOException
{
throw new UnsupportedOperationException();
}
/**
* The length of the stream in bytes. This does not work for "streams"
* that require sequential access.
*
* @return The length of the stream.
*
* @throws UnsupportedOperationException
* If the requested operation is not supported.
* @throws IOException
* If an I/O error occurs.
*/
@Override
public long getLen()
throws UnsupportedOperationException,
IOException
{
throw new UnsupportedOperationException();
}
/**
* Truncates or extends the stream to the specified length if this stream
* supports such an operation. If truncation is requested, all data
* located after this point in the file is discarded. If extending the
* file is requested, the values of the data in the extended portion of
* the file is undefined.
*
* @param len
* The new length of the file.
*
* @throws UnsupportedOperationException
* If the requested operation is not supported.
* @throws IOException
* If an I/O error occurs.
*/
@Override
public void setLen(long len)
throws UnsupportedOperationException,
IOException
{
throw new UnsupportedOperationException();
}
/**
* Write the given character to the output stream.
*
* @param ch
* The character to be written.
*
* @throws IOException
* If an I/O error occurs.
*/
@Override
public void writeCh(char ch)
throws IOException
{
writer.append(ch);
}
/**
* Write the given byte to the output stream.
*
* @param b
* The byte to be written.
*
* @throws IOException
* If an I/O error occurs.
*/
@Override
public void writeByte(byte b)
throws IOException
{
buffer.write(b);
}
/**
* Write the given string to the output stream.
*
* @param data
* The data to be written.
*
* @throws IOException
* If an I/O error occurs.
*/
@Override
public void write(String data)
throws IOException
{
writer.append(data);
}
/**
* Write the given byte array to the output stream.
*
* @param data
* The data to be written.
*
* @throws IOException
* If an I/O error occurs.
*/
@Override
public void write(byte[] data)
throws IOException
{
buffer.write(data);
}
/**
* Write the specified range of bytes from the given byte array to the output stream.
*
* @param data
* The data to be written.
* @param off
* Starting offset in data from which to read bytes to be written. Must be
* non-negative and {@code < data.length}.
* @param len
* Length of data to be written. Must be non-negative and {@code <=
* (data.length - offset)}.
*
* @throws IOException
* If an I/O error occurs.
*/
@Override
public void write(byte[] data, int off, int len)
throws IOException
{
buffer.write(data, off, len);
}
/**
* Peeks at the character from the current read position in the stream (reads a character from
* the current read position in the stream without incrementing stream read position. The next
* {@code peekCh()} and {@code readCh()} will return the same value).
* <p>
* The underlying stream subclass determines the content of the result. Byte oriented streams
* such as pipes or files will return a byte while streams that generate keystrokes or
* characters may return a DBCS or Unicode character.
*
* @return The next character read from the stream, -1 on any failure and -2 upon an
* {@code EOF}.
*/
@Override
public int peekCh()
{
throw new UnsupportedOperationException();
}
/**
* Read a character from the current read position in the stream and increment stream pointer.
* <p>
* The underlying stream subclass determines the content of the result.
* Byte oriented streams such as pipes or files will return a byte while
* streams that generate keystrokes or characters may return a DBCS or
* Unicode character.
*
* @return The next character read from the stream, -1 on any failure
* and -2 upon an <code>EOF</code>.
*/
@Override
public int readCh()
{
throw new UnsupportedOperationException();
}
/**
* Read a single byte from the underlying stream.
*
* @return A single byte from the stream, -1 on any failure and -2 upon an {@code EOF}.
*/
@Override
public int readByte()
{
throw new UnsupportedOperationException();
}
/**
* Read a chunk of bytes from the current read position in the stream to the
* offset calculated by given length or to the <code>EOF</code>, whichever
* comes first. The <code>EOF</code> character is not returned.
*
* @param len
* The number of bytes to read.
*
* @return The chunk read from the stream or <code>null</code> if there
* is nothing to read (the <code>EOF</code> has been reached). The
* length of the returned array will be the smaller of the
* <code>len</code> parameter or the actual bytes left before the
* <code>EOF</code>.
*
* @throws IOException
* If an I/O error occurs.
*/
@Override
public byte[] readBytes(int len)
throws IOException
{
throw new UnsupportedOperationException();
}
/**
* Read all characters from the current read position in the stream to the
* next line separator (as determined by the <code>File.separator</code>
* or to the <code>EOF</code>. Any line separator character(s) and the
* <code>EOF</code> character are not returned.
*
* @return The next line read from the stream.
*
* @throws IOException
* If an I/O error occurs.
* @throws EOFException
* If this input stream reaches the end before reading all the bytes.
* @throws InterruptedException
* If any thread interrupted the current thread before or while the current thread
* was waiting for a notification.
*/
@Override
public String readLn()
throws EOFException,
IOException,
InterruptedException
{
throw new UnsupportedOperationException();
}
/**
* Closes the input stream and releases OS resources associated with it.
*/
@Override
public void closeIn()
{
throw new UnsupportedOperationException();
}
/**
* Closes the output stream and releases OS resources associated with it.
*/
@Override
public void closeOut()
{
try
{
writer.flush();
}
catch (IOException e)
{
}
if (OSResourceManager.getInstance().isServerSide(OsResourceType.STREAMS))
{
// clipboard available only with gui drivers
throw new UnsupportedOperationException();
}
else
{
ThinClient.getInstance().setClipboardValue(new String(buffer.toByteArray(), charset));
}
try
{
writer.close();
}
catch (IOException e)
{
}
}
/**
* Closes both the input and output streams and releases OS resources associated with it.
*/
@Override
public void close()
{
closeOut();
}
/**
* State of the input side of the stream.
*
* @return false
*/
@Override
public boolean isIn()
{
return false;
}
/**
* State of the output side of the stream.
*
* @return true
*/
@Override
public boolean isOut()
{
return true;
}
/**
* Assigns the internal stream reference to the given reference.
*
* @param stream
* The new internal stream reference to use for all operations.
*
* @throws UnsupportedOperationException
* If the requested operation is not supported.
*/
@Override
public void assign(Stream stream)
throws UnsupportedOperationException
{
throw new UnsupportedOperationException();
}
}