public class TextNode extends Node
Node
s representing text files.
Locking
Node uses a ReadWriteLock
to protect most of its state; TextNode
uses the same lock to protect its state, including its text
content.
Memory Management
TextNode
must avoid avoid pinning large numbers of
TextBuffer
s, holding large amounts of character data, in memory. The
chosen mechanism is to automatically close a node, releasing the text
buffer, as soon as all clients using it have dropped their references. Doing
this requires some trickery: TextNode never dispenses the real text buffer,
but instead dispenses a facade which it holds only with a weak reference,
and polls the reference queue to detect when the facade is garbage collected.
When this happens, the node is closed and node closed events are fired. When
the node is dirty, this mechanism is disabled.
LOG_READONLY
Constructor and Description |
---|
TextNode()
Creates a text node with an undefined URL.
|
TextNode(java.net.URL url)
Creates a text node.
|
Modifier and Type | Method and Description |
---|---|
TextBuffer |
acquireTextBuffer()
Gets a
TextBuffer with the content of this node, or null if the
content cannot be loaded. |
TextBuffer |
acquireTextBufferInterruptibly()
Gets a
TextBuffer with the content of this node. |
TextBuffer |
acquireTextBufferOrThrow()
Gets a
TextBuffer with the content of this node. |
boolean |
addTextBufferListener(TextBufferListener listener)
Adds a text buffer listener to the text buffer of this node whether or not
the node is open.
|
boolean |
addWeakTextBufferListener(TextBufferListener listener)
Adds a text bufer listener to the text buffer of this node as its weak listeners.
|
protected void |
closeImpl()
Subclasses should override this method to customize the close()
behavior.
|
protected java.io.OutputStreamWriter |
createOutputStreamWriter(java.io.OutputStream outStream) |
protected java.io.Reader |
createReader(java.net.URL url)
Fetch a Reader for reading the contents of this node from the given
URL.
|
protected FacadeTextBuffer |
facadeBuffer()
Gets the facade text buffer, or null if the node is not open.
|
java.io.InputStream |
getInputStream()
Deprecated.
|
java.io.InputStream |
getInputStream(boolean warn)
Deprecated.
|
java.lang.String |
getLoadEncoding()
Returns a Java supported encoding name to use to
create the InputStreamReader for reading data
from the URL into the TextBuffer (called from revert()).
|
java.io.Reader |
getReader()
Fetch a Reader for accessing the buffer contents of this TextNode.
|
java.lang.String |
getSaveEncoding()
Returns a Java supported encoding name to use to
create the OutputStreamWriter for writing the TextBuffer
to a file (called from save()).
|
protected TextBuffer |
getTextBufferDirectly()
Gets the text buffer if the node is open, or null if not.
|
boolean |
hasEmptyTextBuffer()
Gets whether the TextBuffer for this TextNode is empty.
|
boolean |
isDirty()
First checks if the superclass has its dirty flag set; if so,
returns
true . |
boolean |
isReadOnly()
Returns
true if the Node is read-only. |
void |
markDirty(boolean dirty)
Marks the data with the specified dirty state.
|
protected void |
markDirtyImpl(boolean dirty)
Subclasses should override this method to customize the markDirty()
behavior.
|
protected void |
openImpl()
Subclasses should override this method to customize the open()
behavior.
|
protected void |
readUnlock()
Read unlocks the node for the current thread.
|
void |
releaseTextBuffer()
Informs the document that the previously acquired TextBuffer instance
is no longer needed.
|
void |
removeTextBufferListener(TextBufferListener listener)
Removes a text buffer listener from the text buffer of this node.
|
void |
removeWeakTextBufferListener(TextBufferListener listener)
Removes a text buffer weak listener from the text buffer of this node.
|
protected void |
reportOpenException(java.lang.Exception e)
This routine is given a chance to handle or report an Exception that
occurred during open().
|
protected void |
revertImpl()
Subclasses should override this method to customize the revert()
behavior.
|
protected void |
saveImpl()
Subclasses should override this method to customize the save()
behavior.
|
protected void |
setDefaultLineTerminator(TextBuffer textBuffer)
Sets up the default line terminator to use for the text buffer.
|
void |
setLoadEncoding(java.lang.String loadEncoding)
Sets a Java supported encoding name to use to
create the InputStreamReader for reading data
from the URL into the TextBuffer (called from revert()).
|
void |
setSaveEncoding(java.lang.String saveEncoding)
Sets a Java supported encoding name to use to
create the OutputStreamWriter for writing the TextBuffer
to a file (called from save()).
|
TextBuffer |
tryAcquireTextBuffer()
Non-blocking version of
acquireTextBuffer() . |
protected void |
upgradeUnlock()
Write locks the node for the current thread.
|
protected void |
urlReadOnlyChanged()
Reports that the read-only state of the URL of this node changed.
|
protected void |
writeUnlock()
Read unlocks the node for the current thread.
|
addNodeListener, addNodeListenerForType, addNodeListenerForTypeHierarchy, addWeakNodeListener, attach, beginThreadNodeUsageCycle, callUnderReadLock, callUnderWriteLock, close, createSubject, delete, deleteImpl, detach, endThreadNodeUsage, endThreadNodeUsageCycle, ensureOpen, equalsImpl, getAttributes, getChildren, getData, getIcon, getLongLabel, getShortLabel, getSubject, getTimestamp, getTimestampLoadedUnsafe, getToolTipText, getTransientProperties, getUnmodifiedTimestamp, getURL, isLoaded, isLockHeld, isMigrating, isNew, isOpen, isReadLocked, isReadLockHeld, isReadOrWriteLocked, isTrackedInNodeCache, isTrackingThreadNodeUsage, isWriteLocked, isWriteLockHeld, lockCount, mayHaveChildren, nodeLock, notifyObservers, open, readLock, readLockCount, readLockInterruptibly, refreshTimestamp, removeNodeListener, removeNodeListenerForType, removeNodeListenerForTypeHierarchy, removeWeakNodeListener, rename, renameImpl, revert, runUnderReadLock, runUnderWriteLock, save, setEventLog, setMigrating, setOpen, setReadOnly, setTimestampDirectly, setURL, toString, tryRunUnderReadLock, tryRunUnderWriteLock, unsetMigrating, upgradeLock, writeLock, writeLockCount, writeLockInterruptibly
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
getAttributedLabel
public TextNode()
public TextNode(java.net.URL url)
url
- The URL
of the file represented by this node. The URL
need not represent an existing file.protected void readUnlock()
The Node
implementation invokes readUnlock()
on the
node lock.
Overridden to clear facadeBuffer
when the node is not dirty and
the current thread releases its last lock.
readUnlock
in class Node
protected void writeUnlock()
The Node
implementation invokes writeUnlock()
on
the node lock.
Overridden to clear facadeBuffer
when the node is not dirty and
the current thread releases its last lock.
writeUnlock
in class Node
protected void upgradeUnlock()
writeLock(); try { // access and/or update protected state... } finally { writeUnlock(); }Note that a number of
Node
extensions points are called with a
read or write lock held, and are so documented.
Overridden to clear facadeBuffer
when the node is not dirty and
the current thread releases its last lock.upgradeUnlock
in class Node
protected FacadeTextBuffer facadeBuffer()
facadeBuffer
, is nonnull, use that
(the node is dirty, or this method has already been called in this lock
region);
facadeBufferReference
, is
dereferenceable, use that;
protected void urlReadOnlyChanged()
Node
Node
implementation is empty.
urlReadOnlyChanged
in class Node
public boolean isReadOnly()
true
if the Node is read-only.
TextNode
overrides to force the underlying buffer to be read only.
isReadOnly
in class Node
Node.isReadOnly()
public boolean isDirty()
true
. Otherwise, the determination of
the dirty state is delegated to the underlying TextBuffer
implementation. If the current TextBuffer
is
null
, false
is returned.public void markDirty(boolean dirty)
Node
Note that it can fire nodeDirtyStateChanged()
and UpdateMessage.ATTRIBUTE_CHANGED
events
when node's Node.writeLock()
is held!
protected void markDirtyImpl(boolean dirty)
Node.markDirty(boolean)
invokes this only if the dirty state is
changing, under write lock. The Node
implementation does nothing.
The TextNode
implementation clears the modified
property of the text buffer if the node is open and the dirty state is
cleared.
markDirtyImpl
in class Node
protected void openImpl() throws java.io.IOException
Node
Node.open()
invokes this only if the node is not open, under
write lock. The Node
implementation does nothing.protected void closeImpl() throws java.io.IOException
Node
Node.close()
invokes this only if the node is open, under
write lock. The Node
implementation does nothing.protected void saveImpl() throws java.io.IOException
Node
Node.save()
invokes this only if the node is dirty, under
write lock. The Node
implementation does nothing.protected void revertImpl() throws java.io.IOException
Node
Node.revert()
invokes this only if the node is dirty, under
write lock. The Node
implementation invokes Node.closeImpl()
followed by Node.openImpl()
.revertImpl
in class Node
java.io.IOException
- if an I/O error occurred while revertingprotected void setDefaultLineTerminator(TextBuffer textBuffer)
textBuffer
- the text buffer that backs up the contents
of this nodepublic final TextBuffer acquireTextBuffer()
TextBuffer
with the content of this node, or null if the
content cannot be loaded.public final TextBuffer acquireTextBufferInterruptibly() throws java.io.IOException, java.lang.InterruptedException
TextBuffer
with the content of this node.java.io.IOException
- if the content cannot be loaded.java.lang.InterruptedException
- if the current thread is in or gets put in
the interrupted state. The interrupted state
is cleared when this exception is thrown.public final TextBuffer acquireTextBufferOrThrow() throws java.io.IOException
TextBuffer
with the content of this node.java.io.IOException
- if the content cannot be loaded.public final TextBuffer tryAcquireTextBuffer()
acquireTextBuffer()
. Returns null
immediately if the buffer cannot be obtained without blocking.public final void releaseTextBuffer()
protected TextBuffer getTextBufferDirectly()
public boolean addTextBufferListener(TextBufferListener listener)
Be aware that all text buffer listeners are cleared when the node is closed. Typically, a client using this method from outside of a NodeListener should already have added a NodeListener that will add this text buffer listener on node opened (possibly redundantly).
Also be aware that if the node is not open and never gets opened, the text buffer listeners will never be cleared. Typically, a client using this method when the node may be closed will protect itself against leaking the listener by explicitly removing this text buffer listener as soon as it is no longer needed.
listener
- The text buffer listener.java.lang.IllegalArgumentException
- if the listener is null.public boolean addWeakTextBufferListener(TextBufferListener listener)
listener
are garbage collected, the listener will stop reacting and in
addition it will unregister itself.
This method should be used for TextBufferListeners which are hard to unregister and we want to prevent memory leaks holding these listeners only because they should react to existing TextBuffer.
listener
- The text buffer listener that should be registered as weak listener.java.lang.IllegalArgumentException
- if the listener is null.public void removeTextBufferListener(TextBufferListener listener)
listener
- The text buffer listener.java.lang.IllegalArgumentException
- if the listener is null.public void removeWeakTextBufferListener(TextBufferListener listener)
addWeakTextBufferListener(TextBufferListener)
.
In fact the listener wil unregister itself as soon as all its other instances are garbage collected and TextBuffer
fires any event the listener should react to.listener
- The text buffer listener.public java.io.Reader getReader() throws java.io.IOException
java.io.IOException
public boolean hasEmptyTextBuffer()
public java.lang.String getLoadEncoding()
public java.lang.String getSaveEncoding()
public void setLoadEncoding(java.lang.String loadEncoding)
getLoadEncoding()
with a different encoding
determined from the TextBuffer dataloadEncoding
- a Java supported encoding name for readingpublic void setSaveEncoding(java.lang.String saveEncoding)
getSaveEncoding()
with a different encoding determined from the TextBuffer datasaveEncoding
- a Java supported encoding name for writingprotected java.io.Reader createReader(java.net.URL url) throws java.io.IOException
url
- the URL to fetch a Reader forjava.io.IOException
protected java.io.OutputStreamWriter createOutputStreamWriter(java.io.OutputStream outStream) throws java.io.UnsupportedEncodingException
java.io.UnsupportedEncodingException
public java.io.InputStream getInputStream() throws java.io.IOException
Returns an InputStream
that's backed by the current
TextBuffer
.
getInputStream
in class Node
InputStream
, or null
if the
document has no contents.java.lang.IllegalStateException
- if the current
TextBuffer
is null
.java.net.UnknownServiceException
- if the
URL
's protocol does not support input.java.io.IOException
- if an I/O error occurs when trying to open
the InputStream
.public java.io.InputStream getInputStream(boolean warn) throws java.io.IOException
Returns an InputStream
that's backed by the current
TextBuffer
.
java.lang.IllegalStateException
- if the current
TextBuffer
is null
.java.io.IOException
protected void reportOpenException(java.lang.Exception e)
reportOpenException
in class Node