All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.jackrabbit.vault.fs.io.MemoryArchive Maven / Gradle / Ivy

There is a newer version: 2024.11.18751.20241128T090041Z-241100
Show newest version
/*
 * 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.jackrabbit.vault.fs.io;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.apache.commons.io.IOUtils;
import org.apache.jackrabbit.util.Text;
import org.apache.jackrabbit.vault.fs.api.VaultInputSource;
import org.apache.jackrabbit.vault.fs.config.DefaultMetaInf;
import org.apache.jackrabbit.vault.fs.config.MetaInf;
import org.apache.jackrabbit.vault.fs.config.VaultSettings;
import org.apache.jackrabbit.vault.util.Constants;
import org.apache.jackrabbit.vault.util.InputStreamPump;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Implements an {@link org.apache.jackrabbit.vault.util.InputStreamPump.Pump} that extracts the relevant parts from the input stream into memory.
 * The memory archive is initialized via the {@link #run(InputStream)} being called from {@link InputStreamPump}.
 */
public class MemoryArchive extends AbstractArchive implements InputStreamPump.Pump {

    /**
     * default logger
     */
    private static final Logger log = LoggerFactory.getLogger(MemoryArchive.class);

    private final VirtualEntry root;

    private final DefaultMetaInf inf;

    private boolean cacheMetaOnly = false;

    /**
     * Creates new memory archive.
     * @param metaOnly if {@code true} only the meta info content is cached.
     * @throws IOException if an I/O error occurrs
     */
    public MemoryArchive(boolean metaOnly) throws IOException {
        this.cacheMetaOnly = metaOnly;
        root = new VirtualEntry(null, "", 0, null);
        inf = new DefaultMetaInf();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void run(InputStream in) throws Exception {
        // scan the zip and copy data to temporary file
        ZipInputStream zin = new ZipInputStream(
                new BufferedInputStream(in)
        );
        ZipEntry entry;
        boolean hasRoot = false;
        while ((entry = zin.getNextEntry()) != null) {
            String name = entry.getName();
            boolean isMeta = name.startsWith(Constants.META_DIR + "/");
            if (!hasRoot && name.startsWith(Constants.ROOT_DIR + "/")) {
                hasRoot = true;
            }
            if (isMeta || !cacheMetaOnly) {
                String[] names = Text.explode(name, '/');
                byte[] data = entry.isDirectory() ? null : IOUtils.toByteArray(zin);
                if (names.length > 0) {
                    VirtualEntry je = root;
                    for (int i=0; i children;

        private VirtualEntry(VirtualEntry parent, String name, long time, byte[] data) {
            this.parent = parent;
            this.name = name;
            this.time = time;
            this.data = data;
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public String getName() {
            return name;
        }

        @NotNull
        public String getPath() {
            return getPath(new StringBuilder()).toString();
        }

        @NotNull
        private StringBuilder getPath(@NotNull StringBuilder sb) {
            return parent == null ? sb : parent.getPath(sb).append('/').append(name);
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public boolean isDirectory() {
            return data == null;
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public Collection getChildren() {
            return children == null ? Collections.emptyList() : children.values();
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public Entry getChild(String name) {
            return children == null ? null : children.get(name);
        }

        /**
         * Adds a new child entry.
         * @param name name
         * @param time timestamp
         * @param data data or {@code null}
         * @return the new entry
         */
        @NotNull
        public VirtualEntry add(@NotNull String name, long time, byte[] data) {
            if (children != null) {
                VirtualEntry ret = children.get(name);
                if (ret != null) {
                    return ret;
                }
            }
            VirtualEntry ve = new VirtualEntry(this, name, time, data);
            if (children == null) {
                children = new LinkedHashMap();
            }
            children.put(name, ve);
            return ve;
        }
    }

    /**
     * Safely returns the modification time of the zip entry or 0, if reading the time would
     * result in an error. for example due to http://bugs.java.com/view_bug.do?bug_id=JDK-8184940
     *
     * @param e the zip entry
     * @return the modification time
     */
    private static long safeGetTime(ZipEntry e) {
        try {
            return e.getTime();
        } catch (Exception e1) {
            return 0;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy