001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.harmony.luni.internal.process;
019:
020: import java.io.FileDescriptor;
021: import java.io.IOException;
022: import java.io.OutputStream;
023:
024: class ProcessOutputStream extends OutputStream {
025:
026: private long handle;
027:
028: private FileDescriptor fd;
029:
030: // Fill in the JNI id caches
031: private static native void oneTimeInitialization();
032:
033: static {
034: oneTimeInitialization();
035: }
036:
037: /**
038: * Native to close the stream.
039: */
040: private native void closeImpl() throws IOException;
041:
042: /**
043: * Native to set the FileDescriptor handle.
044: */
045: private native void setFDImpl(FileDescriptor fd, long handle);
046:
047: /**
048: * Native to write the buffer to the stream.
049: */
050: private native void writeImpl(byte[] buf, int offset, int nbytes,
051: long hndl) throws IOException;
052:
053: /**
054: * Open an OutputStream based on the handle.
055: */
056: protected ProcessOutputStream(long handle) {
057: this .fd = new FileDescriptor();
058: setFDImpl(fd, handle);
059: this .handle = handle;
060: }
061:
062: /**
063: * There is no way, at the library/VM level, to know when the stream will be
064: * available for closing. If the user doesn't close it in its code, the
065: * finalize() will run (eventually ?) and close the dangling OS
066: * fileDescriptor.
067: */
068: @Override
069: protected void finalize() throws Throwable {
070: close();
071: }
072:
073: @Override
074: public void close() throws IOException {
075: synchronized (this ) {
076: if (handle == -1) {
077: return;
078: }
079: closeImpl();
080: handle = -1;
081: }
082: }
083:
084: @Override
085: public void write(byte[] buf) throws IOException {
086: synchronized (this ) {
087: writeImpl(buf, 0, buf.length, handle);
088: }
089: }
090:
091: @Override
092: public void write(byte[] buf, int offset, int nbytes)
093: throws IOException {
094: synchronized (this ) {
095: if (handle == -1) {
096: return;
097: }
098: writeImpl(buf, offset, nbytes, handle);
099: }
100: }
101:
102: @Override
103: public void write(int oneByte) throws IOException {
104: byte buf[] = new byte[1];
105: buf[0] = (byte) oneByte;
106: synchronized (this ) {
107: writeImpl(buf, 0, 1, handle);
108: }
109: }
110: }
|