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: package org.apache.commons.vfs.provider;
018:
019: import org.apache.commons.vfs.FileChangeEvent;
020: import org.apache.commons.vfs.FileListener;
021: import org.apache.commons.vfs.FileName;
022: import org.apache.commons.vfs.FileObject;
023: import org.apache.commons.vfs.FileSystemException;
024: import org.apache.commons.vfs.FileType;
025: import org.apache.commons.vfs.FileContentInfo;
026: import org.apache.commons.vfs.RandomAccessContent;
027: import org.apache.commons.vfs.util.WeakRefFileListener;
028: import org.apache.commons.vfs.util.RandomAccessMode;
029:
030: import java.io.InputStream;
031: import java.io.OutputStream;
032: import java.security.cert.Certificate;
033: import java.util.HashSet;
034: import java.util.Map;
035: import java.util.Set;
036:
037: /**
038: * A file backed by another file.
039: *
040: * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
041: * @author Gary D. Gregory
042: * @version $Revision: 537958 $ $Date: 2007-05-14 12:37:15 -0700 (Mon, 14 May 2007) $
043: * @todo Extract subclass that overlays the children
044: */
045: public class DelegateFileObject extends AbstractFileObject implements
046: FileListener {
047: private FileObject file;
048: private final Set children = new HashSet();
049: private boolean ignoreEvent;
050:
051: public DelegateFileObject(final FileName name,
052: final AbstractFileSystem fileSystem, final FileObject file)
053: throws FileSystemException {
054: super (name, fileSystem);
055: this .file = file;
056: if (file != null) {
057: WeakRefFileListener.installListener(file, this );
058: }
059: }
060:
061: /**
062: * get access to the delegated file
063: */
064: public FileObject getDelegateFile() {
065: return file;
066: }
067:
068: /**
069: * Adds a child to this file.
070: */
071: public void attachChild(final FileName baseName, final FileType type)
072: throws Exception {
073: final FileType oldType = doGetType();
074: if (children.add(baseName.getBaseName())) {
075: childrenChanged(baseName, type);
076: }
077: maybeTypeChanged(oldType);
078: }
079:
080: /**
081: * Attaches or detaches the target file.
082: */
083: public void setFile(final FileObject file) throws Exception {
084: final FileType oldType = doGetType();
085:
086: if (file != null) {
087: WeakRefFileListener.installListener(file, this );
088: }
089: this .file = file;
090: maybeTypeChanged(oldType);
091: }
092:
093: /**
094: * Checks whether the file's type has changed, and fires the appropriate
095: * events.
096: */
097: private void maybeTypeChanged(final FileType oldType)
098: throws Exception {
099: final FileType newType = doGetType();
100: if (oldType == FileType.IMAGINARY
101: && newType != FileType.IMAGINARY) {
102: handleCreate(newType);
103: } else if (oldType != FileType.IMAGINARY
104: && newType == FileType.IMAGINARY) {
105: handleDelete();
106: }
107: }
108:
109: /**
110: * Determines the type of the file, returns null if the file does not
111: * exist.
112: */
113: protected FileType doGetType() throws FileSystemException {
114: if (file != null) {
115: return file.getType();
116: } else if (children.size() > 0) {
117: return FileType.FOLDER;
118: } else {
119: return FileType.IMAGINARY;
120: }
121: }
122:
123: /**
124: * Determines if this file can be read.
125: */
126: protected boolean doIsReadable() throws FileSystemException {
127: if (file != null) {
128: return file.isReadable();
129: } else {
130: return true;
131: }
132: }
133:
134: /**
135: * Determines if this file can be written to.
136: */
137: protected boolean doIsWriteable() throws FileSystemException {
138: if (file != null) {
139: return file.isWriteable();
140: } else {
141: return false;
142: }
143: }
144:
145: /**
146: * Determines if this file is hidden.
147: */
148: protected boolean doIsHidden() throws FileSystemException {
149: if (file != null) {
150: return file.isHidden();
151: } else {
152: return false;
153: }
154: }
155:
156: /**
157: * Lists the children of the file.
158: */
159: protected String[] doListChildren() throws Exception {
160: if (file != null) {
161: final FileObject[] children = file.getChildren();
162: final String[] childNames = new String[children.length];
163: for (int i = 0; i < children.length; i++) {
164: childNames[i] = children[i].getName().getBaseName();
165: }
166: return childNames;
167: } else {
168: return (String[]) children.toArray(new String[children
169: .size()]);
170: }
171: }
172:
173: /**
174: * Creates this file as a folder.
175: */
176: protected void doCreateFolder() throws Exception {
177: ignoreEvent = true;
178: try {
179: file.createFolder();
180: } finally {
181: ignoreEvent = false;
182: }
183: }
184:
185: /**
186: * Deletes the file.
187: */
188: protected void doDelete() throws Exception {
189: ignoreEvent = true;
190: try {
191: file.delete();
192: } finally {
193: ignoreEvent = false;
194: }
195: }
196:
197: /**
198: * Returns the size of the file content (in bytes). Is only called if
199: * {@link #doGetType} returns {@link FileType#FILE}.
200: */
201: protected long doGetContentSize() throws Exception {
202: return file.getContent().getSize();
203: }
204:
205: /**
206: * Returns the attributes of this file.
207: */
208: protected Map doGetAttributes() throws Exception {
209: return file.getContent().getAttributes();
210: }
211:
212: /**
213: * Sets an attribute of this file.
214: */
215: protected void doSetAttribute(final String atttrName,
216: final Object value) throws Exception {
217: file.getContent().setAttribute(atttrName, value);
218: }
219:
220: /**
221: * Returns the certificates of this file.
222: */
223: protected Certificate[] doGetCertificates() throws Exception {
224: return file.getContent().getCertificates();
225: }
226:
227: /**
228: * Returns the last-modified time of this file.
229: */
230: protected long doGetLastModifiedTime() throws Exception {
231: return file.getContent().getLastModifiedTime();
232: }
233:
234: /**
235: * Sets the last-modified time of this file.
236: */
237: protected boolean doSetLastModTime(final long modtime)
238: throws Exception {
239: file.getContent().setLastModifiedTime(modtime);
240: return true;
241: }
242:
243: /**
244: * Creates an input stream to read the file content from.
245: */
246: protected InputStream doGetInputStream() throws Exception {
247: return file.getContent().getInputStream();
248: }
249:
250: /**
251: * Creates an output stream to write the file content to.
252: */
253: protected OutputStream doGetOutputStream(boolean bAppend)
254: throws Exception {
255: return file.getContent().getOutputStream(bAppend);
256: }
257:
258: /**
259: * Called when a file is created.
260: */
261: public void fileCreated(final FileChangeEvent event)
262: throws Exception {
263: if (event.getFile() != file) {
264: return;
265: }
266: if (!ignoreEvent) {
267: handleCreate(file.getType());
268: }
269: }
270:
271: /**
272: * Called when a file is deleted.
273: */
274: public void fileDeleted(final FileChangeEvent event)
275: throws Exception {
276: if (event.getFile() != file) {
277: return;
278: }
279: if (!ignoreEvent) {
280: handleDelete();
281: }
282: }
283:
284: /**
285: * Called when a file is changed.
286: * <p/>
287: * This will only happen if you monitor the file using {@link org.apache.commons.vfs.FileMonitor}.
288: */
289: public void fileChanged(FileChangeEvent event) throws Exception {
290: if (event.getFile() != file) {
291: return;
292: }
293: if (!ignoreEvent) {
294: handleChanged();
295: }
296: }
297:
298: /**
299: * Close the delegated file
300: */
301: public void close() throws FileSystemException {
302: super .close();
303:
304: if (file != null) {
305: file.close();
306: }
307: }
308:
309: /**
310: * refresh file informations
311: */
312: public void refresh() throws FileSystemException {
313: super .refresh();
314: if (file != null) {
315: file.refresh();
316: }
317: }
318:
319: protected FileContentInfo doGetContentInfo() throws Exception {
320: return file.getContent().getContentInfo();
321: }
322:
323: /**
324: * Renames the file.
325: */
326: protected void doRename(FileObject newFile) throws Exception {
327: file.moveTo(((DelegateFileObject) newFile).file);
328: }
329:
330: /**
331: * Removes an attribute of this file.
332: */
333: protected void doRemoveAttribute(final String atttrName)
334: throws Exception {
335: file.getContent().removeAttribute(atttrName);
336: }
337:
338: /**
339: * Creates access to the file for random i/o.
340: */
341: protected RandomAccessContent doGetRandomAccessContent(
342: final RandomAccessMode mode) throws Exception {
343: return file.getContent().getRandomAccessContent(mode);
344: }
345: }
|