001: /*
002:
003: Derby - Class org.apache.derby.impl.io.DirFile
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.impl.io;
023:
024: import org.apache.derby.io.StorageFile;
025: import org.apache.derby.io.StorageRandomAccessFile;
026:
027: import org.apache.derby.iapi.services.sanity.SanityManager;
028:
029: import java.io.File;
030: import java.io.InputStream;
031: import java.io.OutputStream;
032: import java.io.FileOutputStream;
033: import java.io.FileInputStream;
034: import java.io.IOException;
035: import java.io.FileNotFoundException;
036: import java.io.RandomAccessFile;
037: import java.net.MalformedURLException;
038: import java.net.URL;
039:
040: /**
041: * This class provides a disk based implementation of the StorageFile interface. It is used by the
042: * database engine to access persistent data and transaction logs under the directory (default) subsubprotocol.
043: */
044: class DirFile extends File implements StorageFile {
045:
046: /**
047: * Construct a DirFile from a path name.
048: *
049: * @param path The path name.
050: */
051: DirFile(String path) {
052: super (path);
053: }
054:
055: /**
056: * Construct a DirFile from a directory name and a file name.
057: *
058: * @param directoryName The directory part of the path name.
059: * @param fileName The name of the file within the directory.
060: */
061: DirFile(String directoryName, String fileName) {
062: super (directoryName, fileName);
063: }
064:
065: /**
066: * Construct a DirFile from a directory name and a file name.
067: *
068: * @param directoryName The directory part of the path name.
069: * @param fileName The name of the file within the directory.
070: */
071: DirFile(DirFile directoryName, String fileName) {
072: super ((File) directoryName, fileName);
073: }
074:
075: /**
076: * Get the name of the parent directory if this name includes a parent.
077: *
078: * @return An StorageFile denoting the parent directory of this StorageFile, if it has a parent, null if
079: * it does not have a parent.
080: */
081: public StorageFile getParentDir() {
082: String parent = getParent();
083: if (parent == null)
084: return null;
085: return new DirFile(parent);
086: }
087:
088: /**
089: * Get the name of the directory of temporary files.
090: *
091: * @return The abstract name of the temp directory;
092: */
093: static StorageFile getTempDir() throws IOException {
094: File temp = File.createTempFile("derby", "tmp");
095: StorageFile parent = new DirFile(temp.getParent());
096: temp.delete();
097:
098: return parent;
099: } // End of getTempDir
100:
101: /**
102: * Creates an output stream from a file name.
103: *
104: * @return an output stream suitable for writing to the file.
105: *
106: * @exception FileNotFoundException if the file exists but is a directory
107: * rather than a regular file, does not exist but cannot be created, or
108: * cannot be opened for any other reason.
109: */
110: public OutputStream getOutputStream() throws FileNotFoundException {
111: return new FileOutputStream((File) this );
112: }
113:
114: /**
115: * Creates an output stream from a file name.
116: *
117: * @param append If true then data will be appended to the end of the file, if it already exists.
118: * If false and a normal file already exists with this name the file will first be truncated
119: * to zero length.
120: *
121: * @return an output stream suitable for writing to the file.
122: *
123: * @exception FileNotFoundException if the file exists but is a directory
124: * rather than a regular file, does not exist but cannot be created, or
125: * cannot be opened for any other reason.
126: */
127: public OutputStream getOutputStream(final boolean append)
128: throws FileNotFoundException {
129: return new FileOutputStream(getPath(), append);
130: }
131:
132: /**
133: * Creates an input stream from a file name.
134: *
135: * @return an input stream suitable for reading from the file.
136: *
137: * @exception FileNotFoundException if the file is not found.
138: */
139: public InputStream getInputStream() throws FileNotFoundException {
140: return new FileInputStream((File) this );
141: }
142:
143: /**
144: * Get an exclusive lock. This is used to ensure that two or more JVMs do not open the same database
145: * at the same time.
146: *
147: *
148: * @return EXCLUSIVE_FILE_LOCK_NOT_AVAILABLE if the lock cannot be acquired because it is already held.<br>
149: * EXCLUSIVE_FILE_LOCK if the lock was successfully acquired.<br>
150: * NO_FILE_LOCK_SUPPORT if the system does not support exclusive locks.<br>
151: */
152: public synchronized int getExclusiveFileLock() {
153: if (exists()) {
154: delete();
155: }
156: try {
157: //Just create an empty file
158: RandomAccessFile lockFileOpen = new RandomAccessFile(
159: (File) this , "rw");
160: lockFileOpen.getFD().sync();
161: lockFileOpen.close();
162: } catch (IOException ioe) {
163: // do nothing - it may be read only medium, who knows what the
164: // problem is
165: if (SanityManager.DEBUG) {
166: SanityManager
167: .THROWASSERT("Unable to create Exclusive Lock File "
168: + getPath());
169: }
170: }
171:
172: return NO_FILE_LOCK_SUPPORT;
173: } // end of getExclusiveFileLock
174:
175: /**
176: * Release the resource associated with an earlier acquired exclusive lock
177: *
178: * @see #getExclusiveFileLock
179: */
180: public synchronized void releaseExclusiveFileLock() {
181: if (exists()) {
182: delete();
183: }
184: } // End of releaseExclusiveFileLock
185:
186: /**
187: * Get a random access (read/write) file.
188: *
189: * @param mode "r", "rw", "rws", or "rwd". The "rws" and "rwd" modes specify
190: * that the data is to be written to persistent store, consistent with the
191: * java.io.RandomAccessFile class ("synchronized" with the persistent
192: * storage, in the file system meaning of the word "synchronized"). However
193: * the implementation is not required to implement the "rws" or "rwd"
194: * modes. The implementation may treat "rws" and "rwd" as "rw". It is up to
195: * the user of this interface to call the StorageRandomAccessFile.sync
196: * method. If the "rws" or "rwd" modes are supported and the
197: * RandomAccessFile was opened in "rws" or "rwd" mode then the
198: * implementation of StorageRandomAccessFile.sync need not do anything.
199: *
200: * @return an object that can be used for random access to the file.
201: *
202: * @exception IllegalArgumentException if the mode argument is not equal to one of "r", "rw".
203: * @exception FileNotFoundException if the file exists but is a directory rather than a regular
204: * file, or cannot be opened or created for any other reason .
205: */
206: public StorageRandomAccessFile getRandomAccessFile(String mode)
207: throws FileNotFoundException {
208: // Assume that modes "rws" and "rwd" are not supported.
209: if ("rws".equals(mode) || "rwd".equals(mode))
210: mode = "rw";
211: return new DirRandomAccessFile((File) this , mode);
212: } // end of getRandomAccessFile
213:
214: /**
215: * Rename the file denoted by this name. Note that StorageFile objects are immutable. This method
216: * renames the underlying file, it does not change this StorageFile object. The StorageFile object denotes the
217: * same name as before, however the exists() method will return false after the renameTo method
218: * executes successfully.
219: *
220: *<p>It is not specified whether this method will succeed if a file already exists under the new name.
221: *
222: * @param newName the new name.
223: *
224: * @return <b>true</b> if the rename succeeded, <b>false</b> if not.
225: */
226: public boolean renameTo(StorageFile newName) {
227: return super .renameTo((File) newName);
228: }
229:
230: /**
231: * Deletes the named file and, if it is a directory, all the files and directories it contains.
232: *
233: * @return <b>true</b> if the named file or directory is successfully deleted, <b>false</b> if not
234: */
235: public boolean deleteAll() {
236: if (!exists())
237: return false;
238: if (isDirectory()) {
239: String[] childList = super .list();
240: String parentName = getPath();
241: for (int i = 0; i < childList.length; i++) {
242: if (childList[i].equals(".")
243: || childList[i].equals(".."))
244: continue;
245: DirFile child = new DirFile(parentName, childList[i]);
246: if (!child.deleteAll())
247: return false;
248: }
249: }
250: return delete();
251: } // end of deleteAll
252:
253: /**
254: * @see org.apache.derby.io.StorageFile#getURL()
255: */
256: public URL getURL() throws MalformedURLException {
257:
258: return toURL();
259: }
260: }
|