| |
| /* ==================================================================== |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| ==================================================================== */ |
| |
| |
| package org.apache.poi.poifs.filesystem; |
| |
| import java.io.FileNotFoundException; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.apache.poi.hpsf.ClassID; |
| |
| /** |
| * A DirectoryEntry filter, which exposes another |
| * DirectoryEntry less certain parts. |
| * This is typically used when copying or comparing |
| * Filesystems. |
| */ |
| public class FilteringDirectoryNode implements DirectoryEntry |
| { |
| /** |
| * The names of our entries to exclude |
| */ |
| private Set<String> excludes; |
| /** |
| * Excludes of our child directories |
| */ |
| private Map<String,List<String>> childExcludes; |
| |
| private DirectoryEntry directory; |
| |
| /** |
| * Creates a filter round the specified directory, which |
| * will exclude entries such as "MyNode" and "MyDir/IgnoreNode". |
| * The excludes can stretch into children, if they contain a /. |
| * |
| * @param directory The Directory to filter |
| * @param excludes The Entries to exclude |
| */ |
| public FilteringDirectoryNode(DirectoryEntry directory, Collection<String> excludes) { |
| this.directory = directory; |
| |
| // Process the excludes |
| this.excludes = new HashSet<String>(); |
| this.childExcludes = new HashMap<String, List<String>>(); |
| for (String excl : excludes) { |
| int splitAt = excl.indexOf('/'); |
| if (splitAt == -1) { |
| // Applies to us |
| this.excludes.add(excl); |
| } else { |
| // Applies to a child |
| String child = excl.substring(0, splitAt); |
| String childExcl = excl.substring(splitAt+1); |
| if (! this.childExcludes.containsKey(child)) { |
| this.childExcludes.put(child, new ArrayList<String>()); |
| } |
| this.childExcludes.get(child).add(childExcl); |
| } |
| } |
| } |
| |
| public DirectoryEntry createDirectory(String name) throws IOException { |
| return directory.createDirectory(name); |
| } |
| |
| public DocumentEntry createDocument(String name, InputStream stream) |
| throws IOException { |
| return directory.createDocument(name, stream); |
| } |
| |
| public DocumentEntry createDocument(String name, int size, |
| POIFSWriterListener writer) throws IOException { |
| return directory.createDocument(name, size, writer); |
| } |
| |
| public Iterator<Entry> getEntries() { |
| return new FilteringIterator(); |
| } |
| |
| public Iterator<Entry> iterator() { |
| return getEntries(); |
| } |
| |
| public int getEntryCount() { |
| int size = directory.getEntryCount(); |
| for (String excl : excludes) { |
| if (directory.hasEntry(excl)) { |
| size--; |
| } |
| } |
| return size; |
| } |
| |
| public Set<String> getEntryNames() { |
| Set<String> names = new HashSet<String>(); |
| for (String name : directory.getEntryNames()) { |
| if (!excludes.contains(name)) { |
| names.add(name); |
| } |
| } |
| return names; |
| } |
| |
| public boolean isEmpty() { |
| return (getEntryCount() == 0); |
| } |
| |
| public boolean hasEntry(String name) { |
| if (excludes.contains(name)) { |
| return false; |
| } |
| return directory.hasEntry(name); |
| } |
| |
| public Entry getEntry(String name) throws FileNotFoundException { |
| if (excludes.contains(name)) { |
| throw new FileNotFoundException(name); |
| } |
| |
| Entry entry = directory.getEntry(name); |
| return wrapEntry(entry); |
| } |
| private Entry wrapEntry(Entry entry) { |
| String name = entry.getName(); |
| if (childExcludes.containsKey(name) && entry instanceof DirectoryEntry) { |
| return new FilteringDirectoryNode( |
| (DirectoryEntry)entry, childExcludes.get(name)); |
| } |
| return entry; |
| } |
| |
| public ClassID getStorageClsid() { |
| return directory.getStorageClsid(); |
| } |
| |
| public void setStorageClsid(ClassID clsidStorage) { |
| directory.setStorageClsid(clsidStorage); |
| } |
| |
| public boolean delete() { |
| return directory.delete(); |
| } |
| |
| public boolean renameTo(String newName) { |
| return directory.renameTo(newName); |
| } |
| |
| public String getName() { |
| return directory.getName(); |
| } |
| |
| public DirectoryEntry getParent() { |
| return directory.getParent(); |
| } |
| |
| public boolean isDirectoryEntry() { |
| return true; |
| } |
| |
| public boolean isDocumentEntry() { |
| return false; |
| } |
| |
| private class FilteringIterator implements Iterator<Entry> { |
| private Iterator<Entry> parent; |
| private Entry next; |
| |
| private FilteringIterator() { |
| parent = directory.getEntries(); |
| locateNext(); |
| } |
| private void locateNext() { |
| next = null; |
| Entry e; |
| while (parent.hasNext() && next == null) { |
| e = parent.next(); |
| if (! excludes.contains(e.getName())) { |
| next = wrapEntry(e); |
| } |
| } |
| } |
| |
| public boolean hasNext() { |
| return (next != null); |
| } |
| |
| public Entry next() { |
| Entry e = next; |
| locateNext(); |
| return e; |
| } |
| |
| public void remove() { |
| throw new UnsupportedOperationException("Remove not supported"); |
| } |
| } |
| } |