001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.vfs2.provider.jar;
018
019import java.io.File;
020import java.io.IOException;
021import java.util.Collection;
022import java.util.jar.Attributes;
023import java.util.jar.Attributes.Name;
024import java.util.jar.JarFile;
025import java.util.jar.Manifest;
026import java.util.zip.ZipEntry;
027import java.util.zip.ZipFile;
028
029import org.apache.commons.vfs2.Capability;
030import org.apache.commons.vfs2.FileObject;
031import org.apache.commons.vfs2.FileSystemException;
032import org.apache.commons.vfs2.FileSystemOptions;
033import org.apache.commons.vfs2.provider.AbstractFileName;
034import org.apache.commons.vfs2.provider.zip.ZipFileObject;
035import org.apache.commons.vfs2.provider.zip.ZipFileSystem;
036
037/**
038 * A read-only file system for Jar files.
039 */
040public class JarFileSystem extends ZipFileSystem {
041    private Attributes attributes;
042
043    /**
044     * Constructs a new instance.
045     *
046     * @param rootFileName The root file name of this file system.
047     * @param parentLayer The parent layer of this file system.
048     * @param fileSystemOptions Options to build this file system.
049     * @throws FileSystemException If the parent layer does not exist, or on error replicating the file.
050     */
051    protected JarFileSystem(final AbstractFileName rootFileName, final FileObject parentLayer, final FileSystemOptions fileSystemOptions)
052            throws FileSystemException {
053        super(rootFileName, parentLayer, fileSystemOptions);
054    }
055
056    // @Override
057    // protected FileObject createFile(AbstractFileName name) throws FileSystemException
058    // {
059    // return new JarFileObject(name, null, this, false);
060    // }
061
062    /**
063     * Returns the capabilities of this file system.
064     */
065    @Override
066    protected void addCapabilities(final Collection<Capability> caps) {
067        // super.addCapabilities(caps);
068        caps.addAll(JarFileProvider.CAPABILITIES);
069    }
070
071    @Override
072    protected ZipFile createZipFile(final File file) throws FileSystemException {
073        try {
074            return new JarFile(file);
075        } catch (final IOException ioe) {
076            throw new FileSystemException("vfs.provider.jar/open-jar-file.error", file, ioe);
077        }
078    }
079
080    @Override
081    protected ZipFileObject createZipFileObject(final AbstractFileName name, final ZipEntry entry)
082            throws FileSystemException {
083        return new JarFileObject(name, entry, this, true);
084    }
085
086    Object getAttribute(final Name attrName) throws FileSystemException {
087        try {
088            final Attributes attr = getAttributes();
089            return attr.getValue(attrName);
090        } catch (final IOException ioe) {
091            throw new FileSystemException(attrName.toString(), ioe);
092        }
093    }
094
095    /**
096     * Retrieves the attribute with the specified name. The default implementation simply throws an exception.
097     *
098     * @param attrName The attribute's name.
099     * @return The value of the attribute.
100     * @throws FileSystemException if an error occurs.
101     */
102    @Override
103    public Object getAttribute(final String attrName) throws FileSystemException {
104        final Name name = lookupName(attrName);
105        return getAttribute(name);
106    }
107
108    Attributes getAttributes() throws IOException {
109        if (attributes == null) {
110            final Manifest man = ((JarFile) getZipFile()).getManifest();
111            if (man == null) {
112                attributes = new Attributes(1);
113            } else {
114                attributes = man.getMainAttributes();
115                if (attributes == null) {
116                    attributes = new Attributes(1);
117                }
118            }
119        }
120
121        return attributes;
122    }
123
124    @Override
125    protected ZipFile getZipFile() throws FileSystemException {
126        // make accessible
127        return super.getZipFile();
128    }
129
130    Name lookupName(final String attrName) {
131        if (Name.CLASS_PATH.toString().equals(attrName)) {
132            return Name.CLASS_PATH;
133        }
134        if (Name.CONTENT_TYPE.toString().equals(attrName)) {
135            return Name.CONTENT_TYPE;
136        }
137        if (Name.EXTENSION_INSTALLATION.toString().equals(attrName)) {
138            return Name.EXTENSION_INSTALLATION;
139        }
140        if (Name.EXTENSION_LIST.toString().equals(attrName)) {
141            return Name.EXTENSION_LIST;
142        }
143        if (Name.EXTENSION_NAME.toString().equals(attrName)) {
144            return Name.EXTENSION_NAME;
145        }
146        if (Name.IMPLEMENTATION_TITLE.toString().equals(attrName)) {
147            return Name.IMPLEMENTATION_TITLE;
148        }
149        if (Name.IMPLEMENTATION_URL.toString().equals(attrName)) {
150            return Name.IMPLEMENTATION_URL;
151        }
152        if (Name.IMPLEMENTATION_VENDOR.toString().equals(attrName)) {
153            return Name.IMPLEMENTATION_VENDOR;
154        }
155        if (Name.IMPLEMENTATION_VENDOR_ID.toString().equals(attrName)) {
156            return Name.IMPLEMENTATION_VENDOR_ID;
157        }
158        if (Name.IMPLEMENTATION_VERSION.toString().equals(attrName)) {
159            return Name.IMPLEMENTATION_VENDOR;
160        }
161        if (Name.MAIN_CLASS.toString().equals(attrName)) {
162            return Name.MAIN_CLASS;
163        }
164        if (Name.MANIFEST_VERSION.toString().equals(attrName)) {
165            return Name.MANIFEST_VERSION;
166        }
167        if (Name.SEALED.toString().equals(attrName)) {
168            return Name.SEALED;
169        }
170        if (Name.SIGNATURE_VERSION.toString().equals(attrName)) {
171            return Name.SIGNATURE_VERSION;
172        }
173        if (Name.SPECIFICATION_TITLE.toString().equals(attrName)) {
174            return Name.SPECIFICATION_TITLE;
175        }
176        if (Name.SPECIFICATION_VENDOR.toString().equals(attrName)) {
177            return Name.SPECIFICATION_VENDOR;
178        }
179        if (Name.SPECIFICATION_VERSION.toString().equals(attrName)) {
180            return Name.SPECIFICATION_VERSION;
181        }
182        return new Name(attrName);
183    }
184
185}