/* ****************************************************************************** * Copyright (c) 2006-2012 XMind Ltd. and others. * * This file is a part of XMind 3. XMind releases 3 and * above are dual-licensed under the Eclipse Public License (EPL), * which is available at http://www.eclipse.org/legal/epl-v10.html * and the GNU Lesser General Public License (LGPL), * which is available at http://www.gnu.org/licenses/lgpl.html * See http://www.xmind.net/license.html for details. * * Contributors: * XMind Ltd. - initial API and implementation *******************************************************************************/ package org.xmind.core.internal.dom; import static org.xmind.core.internal.dom.DOMConstants.ATTR_FULL_PATH; import static org.xmind.core.internal.dom.DOMConstants.ATTR_MEDIA_TYPE; import static org.xmind.core.internal.dom.DOMConstants.TAG_ENCRYPTION_DATA; import static org.xmind.core.internal.dom.InternalDOMUtils.getParentPath; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Iterator; import org.w3c.dom.Element; import org.xmind.core.CoreException; import org.xmind.core.IEncryptionData; import org.xmind.core.IEntryStreamNormalizer; import org.xmind.core.IFileEntry; import org.xmind.core.IFileEntryFilter; import org.xmind.core.IManifest; import org.xmind.core.IWorkbook; import org.xmind.core.internal.FileEntry; import org.xmind.core.io.CoreIOException; import org.xmind.core.io.IInputSource; import org.xmind.core.io.IStorage; import org.xmind.core.util.DOMUtils; public class FileEntryImpl extends FileEntry { private Element implementation; private ManifestImpl ownedManifest; private Integer refCount = null; private EncryptionDataImpl encData; private boolean ignoreEncryption = false; public FileEntryImpl(Element implementation, ManifestImpl ownedManifest) { this.implementation = implementation; this.ownedManifest = ownedManifest; } public Element getImplementation() { return implementation; } public String getMediaType() { return implementation.getAttribute(ATTR_MEDIA_TYPE); } public IManifest getOwnedManifest() { return ownedManifest; } public String getPath() { return implementation.getAttribute(ATTR_FULL_PATH); } public <T> T getAdapter(Class<T> adapter) { if (adapter.isAssignableFrom(Element.class)) return adapter.cast(implementation); return super.getAdapter(adapter); } public boolean equals(Object obj) { if (obj == this) return true; if (obj == null || !(obj instanceof FileEntryImpl)) return false; FileEntryImpl that = (FileEntryImpl) obj; return this.implementation == that.implementation; } public int hashCode() { return implementation.hashCode(); } public String toString() { return DOMUtils.toString(implementation); } public int getReferenceCount() { return refCount == null ? 0 : refCount.intValue(); } public boolean hasBeenReferred() { return refCount != null; } public void increaseReference() { int c = getReferenceCount(); refCount = Integer.valueOf(c + 1); if (c <= 0) { ownedManifest.insertFileEntry(this); } String parent = getParentPath(getPath()); if (parent != null) { IFileEntry parentEntry = ownedManifest.getFileEntry(parent); if (parentEntry != null) parentEntry.increaseReference(); } } public void decreaseReference() { if (refCount == null) return; int c = refCount.intValue(); c--; refCount = Integer.valueOf(c); if (c <= 0) { ownedManifest.removeFileEntry(this); } String parent = getParentPath(getPath()); if (parent != null) { IFileEntry parentEntry = ownedManifest.getFileEntry(parent); if (parentEntry != null) parentEntry.decreaseReference(); } } private IStorage getStorage() { return ownedManifest.getStorage(); } @Deprecated public InputStream getInputStream() { if (isDirectory()) return null; IStorage storage = getStorage(); if (storage != null) { String path = getPath(); return storage.getInputSource().getEntryStream(path); } return null; } @Deprecated public OutputStream getOutputStream() { if (isDirectory()) return null; IStorage storage = getStorage(); if (storage != null) { return storage.getOutputTarget().getEntryStream(getPath()); } return null; } public boolean canRead() { IStorage storage = getStorage(); if (storage != null) { IInputSource source = storage.getInputSource(); return source.hasEntry(getPath()) && source.isEntryAvailable(getPath()); } return false; } public boolean canWrite() { IStorage storage = getStorage(); if (storage != null) { return storage.getOutputTarget().isEntryAvaialble(getPath()); } return false; } public InputStream openInputStream() throws IOException { if (isDirectory()) throw new FileNotFoundException(getPath()); IStorage storage = getStorage(); if (storage == null) throw new FileNotFoundException(getPath()); IInputSource inputSource = storage.getInputSource(); if (!inputSource.hasEntry(getPath())) throw new FileNotFoundException(getPath()); InputStream stream = inputSource.openEntryStream(getPath()); IEntryStreamNormalizer encryptionHandler = ownedManifest .getStreamNormalizer(); if (!isIgnoreEncryption() && encryptionHandler != null) { try { stream = encryptionHandler.normalizeInputStream(stream, this); } catch (CoreException e) { throw new CoreIOException(e); } } return stream; } public OutputStream openOutputStream() throws IOException { if (isDirectory()) throw new FileNotFoundException(getPath()); IStorage storage = getStorage(); if (storage == null) throw new FileNotFoundException(getPath()); OutputStream stream = storage.getOutputTarget() .openEntryStream(getPath()); IEntryStreamNormalizer encryptionHandler = ownedManifest .getStreamNormalizer(); if (!isIgnoreEncryption() && encryptionHandler != null) { try { stream = encryptionHandler.normalizeOutputStream(stream, this); } catch (CoreException e) { throw new CoreIOException(e); } } return stream; } public long getTime() { IStorage storage = getStorage(); if (storage != null) return storage.getInputSource().getEntryTime(getPath()); return -1; } public void setTime(long time) { IStorage storage = getStorage(); if (storage != null) { storage.getOutputTarget().setEntryTime(getPath(), time); } } /* * (non-Javadoc) * @see org.xmind.core.IFileEntry#iterSubEntries() */ public Iterator<IFileEntry> iterSubEntries() { final String parentPath = getPath(); return ownedManifest.iterFileEntries(new IFileEntryFilter() { public boolean select(String path, String mediaType, boolean isDirectory) { return path.length() > parentPath.length() && path.startsWith(parentPath); } }); } public boolean isDirectory() { return getPath().endsWith("/"); //$NON-NLS-1$ } public long getSize() { IStorage storage = getStorage(); if (storage != null) { return storage.getInputSource().getEntrySize(getPath()); } return -1; } /* * (non-Javadoc) * @see org.xmind.core.IFileEntry#getEncryptionData() */ public IEncryptionData getEncryptionData() { Element encEle = DOMUtils.getFirstChildElementByTag(implementation, TAG_ENCRYPTION_DATA); if (encEle == null) { if (encData != null) { encData = null; } } else { if (encData == null) { encData = new EncryptionDataImpl(encEle, this); } } return encData; } /* * (non-Javadoc) * @see org.xmind.core.IFileEntry#createEncryptionData() */ public IEncryptionData createEncryptionData() { IEncryptionData ed = getEncryptionData(); if (ed != null) return ed; Element encEle = DOMUtils.createElement(implementation, TAG_ENCRYPTION_DATA); encData = new EncryptionDataImpl(encEle, this); return encData; } /* * (non-Javadoc) * @see org.xmind.core.IFileEntry#deleteEncryptionData() */ public void deleteEncryptionData() { getEncryptionData(); if (encData != null) { Element encEle = encData.getImplementation(); if (encEle != null && encEle.getParentNode() == implementation) { implementation.removeChild(encEle); } encData = null; } } /** * @param ignoreEncryption * the ignoreEncryption to set * @deprecated */ public void setIgnoreEncryption(boolean ignoreEncryption) { this.ignoreEncryption = ignoreEncryption; } /** * @return the ignoreEncryption * @deprecated */ public boolean isIgnoreEncryption() { return ignoreEncryption; } public IWorkbook getOwnedWorkbook() { return ownedManifest.getOwnedWorkbook(); } public boolean isOrphan() { return DOMUtils.isOrphanNode(getImplementation()); } }