001/*
002 * JDrupes Builder
003 * Copyright (C) 2025 Michael N. Lipp
004 * 
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU Affero General Public License as
007 * published by the Free Software Foundation, either version 3 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013 * GNU Affero General Public License for more details.
014 *
015 * You should have received a copy of the GNU Affero General Public License
016 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
017 */
018
019package org.jdrupes.builder.java;
020
021import java.io.IOException;
022import java.io.InputStream;
023import java.io.OutputStream;
024import java.time.Instant;
025import java.util.Objects;
026import java.util.Optional;
027import java.util.jar.JarEntry;
028import java.util.jar.JarFile;
029import org.jdrupes.builder.api.BuildException;
030import org.jdrupes.builder.api.IOResource;
031import org.jdrupes.builder.core.ResourceObject;
032
033/// Represents an entry in a jar file.
034///
035public class JarFileEntry extends ResourceObject implements IOResource {
036
037    private final JarFile jarFile;
038    private final JarEntry entry;
039
040    /// Initializes a new jar file entry.
041    ///
042    /// @param jarFile the jar file
043    /// @param entry the entry
044    ///
045    public JarFileEntry(JarFile jarFile, JarEntry entry) {
046        super();
047        this.jarFile = jarFile;
048        this.entry = entry;
049    }
050
051    @Override
052    public Optional<Instant> asOf() {
053        return Optional.of(entry.getLastModifiedTime().toInstant());
054    }
055
056    @Override
057    public InputStream inputStream() {
058        try {
059            return jarFile.getInputStream(entry);
060        } catch (IOException e) {
061            throw new BuildException().cause(e);
062        }
063    }
064
065    @Override
066    public OutputStream outputStream() {
067        throw new UnsupportedOperationException();
068    }
069
070    @Override
071    public int hashCode() {
072        final int prime = 31;
073        int result = super.hashCode();
074        result
075            = prime * result + Objects.hash(entry.getName(), jarFile.getName());
076        return result;
077    }
078
079    @Override
080    public boolean equals(Object obj) {
081        if (this == obj) {
082            return true;
083        }
084        if (!super.equals(obj)) {
085            return false;
086        }
087        return (obj instanceof JarFileEntry other)
088            && Objects.equals(entry.getName(), other.entry.getName())
089            && Objects.equals(jarFile.getName(), other.jarFile.getName());
090    }
091
092    @Override
093    public String toString() {
094        return jarFile.getName() + "!" + entry.getName() + " ("
095            + asOfLocalized() + ")";
096    }
097
098}