/* * ============================================================================ * GNU General Public License * ============================================================================ * * Copyright (C) 2006-2011 Serotonin Software Technologies Inc. http://serotoninsoftware.com * @author Matthew Lohbihler * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU 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 General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * When signing a commercial license with Serotonin Software Technologies Inc., * the following extension to GPL is made. A special exception to the GPL is * included to allow you to distribute a combined work that includes BAcnet4J * without being obliged to provide the source code for any proprietary components. */ package com.serotonin.bacnet4j.obj; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.RandomAccessFile; import java.math.BigInteger; import com.serotonin.bacnet4j.LocalDevice; import com.serotonin.bacnet4j.exception.BACnetRuntimeException; import com.serotonin.bacnet4j.exception.BACnetServiceException; import com.serotonin.bacnet4j.type.constructed.DateTime; import com.serotonin.bacnet4j.type.enumerated.FileAccessMethod; import com.serotonin.bacnet4j.type.enumerated.PropertyIdentifier; import com.serotonin.bacnet4j.type.primitive.Boolean; import com.serotonin.bacnet4j.type.primitive.ObjectIdentifier; import com.serotonin.bacnet4j.type.primitive.OctetString; import com.serotonin.bacnet4j.type.primitive.UnsignedInteger; import org.free.bacnet4j.util.StreamUtils; /** * @author Matthew Lohbihler */ public class FileObject extends BACnetObject { private static final long serialVersionUID = 1089963077847602732L; /** * The actual file that this object represents. */ private final File file; public FileObject(LocalDevice localDevice, ObjectIdentifier oid, File file, FileAccessMethod fileAccessMethod) { super(localDevice, oid); this.file = file; if (file.isDirectory()) throw new BACnetRuntimeException("File is a directory"); updateProperties(); try { setProperty(PropertyIdentifier.fileAccessMethod, fileAccessMethod); } catch (BACnetServiceException e) { // Should never happen, but wrap in an unchecked just in case. throw new BACnetRuntimeException(e); } } public void updateProperties() { try { // TODO this is only a snapshot. Property read methods need to be overridden to report real time values. setProperty(PropertyIdentifier.fileSize, new UnsignedInteger(new BigInteger(Long.toString(length())))); setProperty(PropertyIdentifier.modificationDate, new DateTime(file.lastModified())); setProperty(PropertyIdentifier.readOnly, new Boolean(!file.canWrite())); } catch (BACnetServiceException e) { // Should never happen, but wrap in an unchecked just in case. throw new BACnetRuntimeException(e); } } public long length() { return file.length(); } public OctetString readData(long start, long length) throws IOException { FileInputStream in = new FileInputStream(file); try { while (start > 0) { long result = in.skip(start); if (result == -1) // EOF break; start -= result; } ByteArrayOutputStream out = new ByteArrayOutputStream(); StreamUtils.transfer(in, out, length); return new OctetString(out.toByteArray()); } finally { in.close(); } } public void writeData(long start, OctetString fileData) throws IOException { RandomAccessFile raf = new RandomAccessFile(file, "rw"); try { byte data[] = fileData.getBytes(); long newLength = start + data.length; raf.seek(start); raf.write(data); raf.setLength(newLength); } finally { raf.close(); } updateProperties(); } // // public SequenceOf<OctetString> readRecords(int start, int length) throws IOException { // // } }