Java tutorial
/** * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. * If a copy of the MPL was not distributed with this file, You can obtain one at * http://mozilla.org/MPL/2.0/. * * This Source Code Form is also subject to the terms of the Health-Related Additional * Disclaimer of Warranty and Limitation of Liability available at * http://www.carewebframework.org/licensing/disclaimer. */ package org.carewebframework.help.chm.maven; import java.io.ByteArrayInputStream; import java.io.File; import java.io.InputStream; import java.util.Iterator; import java.util.Set; import java.util.TreeSet; import org.apache.commons.io.FileUtils; import org.apache.tika.exception.TikaException; import org.apache.tika.parser.chm.accessor.DirectoryListingEntry; import org.apache.tika.parser.chm.core.ChmCommons; import org.apache.tika.parser.chm.core.ChmExtractor; import org.carewebframework.maven.plugin.iterator.IResourceIterator; import org.carewebframework.maven.plugin.resource.IResource; /** * Used where source archive is a chm file format. Uses the Tika CHM extractor to extract files from * the source archive. */ public class ChmSource implements IResourceIterator { /** * Wraps a DirectoryListingEntry as an IResource. */ protected class ChmEntry implements IResource, Comparable<ChmEntry> { private final boolean isDirectory; private final DirectoryListingEntry entry; private final String sourcePath; private ChmEntry(DirectoryListingEntry entry) throws TikaException { String name = entry.getName(); isDirectory = name.endsWith("/"); sourcePath = name.startsWith("/") ? name.substring(1) : name; // Note: if the extractor would normally skip this entry, tweak its name to force inclusion. if (ChmCommons.hasSkip(entry)) { entry = new DirectoryListingEntry(entry.getNameLength(), "_" + sourcePath, entry.getEntryType(), entry.getOffset(), entry.getLength()); } this.entry = entry; } @Override public String getSourcePath() { return sourcePath; } /** * Need to explicitly translate #SYSTEM target here so that the Spring configuration file is * generated correctly. */ @Override public String getTargetPath() { return "#SYSTEM".equals(sourcePath) ? "helpset.xml" : sourcePath; } @Override public boolean isDirectory() { return isDirectory; } @Override public InputStream getInputStream() { try { return new ByteArrayInputStream(chmExtractor.extractChmEntry(entry)); } catch (TikaException e) { throw new RuntimeException(e); } } @Override public int compareTo(ChmEntry tgt) { return sourcePath.compareTo(tgt.sourcePath); } @Override public boolean equals(Object tgt) { return tgt instanceof ChmEntry && compareTo((ChmEntry) tgt) == 0; } @Override public long getTime() { return timestamp; } /** * Retrieves an input stream for a companion resource. * * @param file Name of the resource file. * @return The input stream or null if not found. */ public InputStream getInputStream(String file) { ChmEntry resource = findEntry(file); return resource == null ? null : resource.getInputStream(); } } private final ChmExtractor chmExtractor; private final Set<ChmEntry> entries; private final Iterator<ChmEntry> iterator; private final long timestamp = System.currentTimeMillis(); /** * Wraps a chm file as an IResourceIterator. * * @param chmFile The chm file. */ public ChmSource(String chmFile) { try (InputStream inp = FileUtils.openInputStream(new File(chmFile));) { chmExtractor = new ChmExtractor(inp); entries = buildEntryList(); iterator = entries.iterator(); } catch (Exception e) { throw new RuntimeException(e); } } /** * Builds the list of archive file entries. * * @throws TikaException Unspecified exception. */ private Set<ChmEntry> buildEntryList() throws TikaException { Set<ChmEntry> entries = new TreeSet<>(); for (DirectoryListingEntry entry : chmExtractor.getChmDirList().getDirectoryListingEntryList()) { String name = entry.getName(); if (name.startsWith("/") && !name.equals("/") && !name.startsWith("/$")) { entries.add(new ChmEntry(entry)); } } return entries; } /** * Returns the chm entry that references the specified file name. * * @param file A file name. * @return The CHMEntry referencing the specified file, or null if not found. */ private ChmEntry findEntry(String file) { for (ChmEntry entry : entries) { if (file.equals(entry.getSourcePath())) { return entry; } } return null; } @Override public void close() { } @Override public boolean hasNext() { return iterator.hasNext(); } @Override public IResource next() { return iterator.next(); } @Override public void remove() { iterator.remove(); } }