001/*
002 * Copyright (C) 2014 Jörg Prante
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.xbib.elasticsearch.plugin.jdbc.classloader.jar;
017
018import org.xbib.elasticsearch.plugin.jdbc.classloader.AbstractResourceHandle;
019import org.xbib.elasticsearch.plugin.jdbc.classloader.AbstractURLResourceLocation;
020import org.xbib.elasticsearch.plugin.jdbc.classloader.ResourceHandle;
021
022import java.io.ByteArrayInputStream;
023import java.io.ByteArrayOutputStream;
024import java.io.File;
025import java.io.FileInputStream;
026import java.io.IOException;
027import java.io.InputStream;
028import java.net.MalformedURLException;
029import java.net.URL;
030import java.util.jar.JarEntry;
031import java.util.jar.JarFile;
032import java.util.jar.JarInputStream;
033import java.util.jar.Manifest;
034import java.util.zip.ZipException;
035
036public class JarResourceLocation extends AbstractURLResourceLocation {
037
038    private JarFile jarFile;
039
040    private byte content[];
041
042    public JarResourceLocation(URL codeSource, File cacheFile) throws IOException {
043        super(codeSource);
044        try {
045            jarFile = new JarFile(cacheFile);
046        } catch (ZipException ze) {
047            // We get this exception on windows when the
048            // path to the jar file gets too long (Bug ID: 6374379)
049            InputStream is = null;
050            try {
051                is = new FileInputStream(cacheFile);
052                ByteArrayOutputStream baos = new ByteArrayOutputStream();
053                byte[] buffer = new byte[2048];
054                int bytesRead;
055                while ((bytesRead = is.read(buffer)) != -1) {
056                    baos.write(buffer, 0, bytesRead);
057                }
058                this.content = baos.toByteArray();
059            } finally {
060                if (is != null) {
061                    is.close();
062                }
063            }
064        }
065    }
066
067    public ResourceHandle getResourceHandle(String resourceName) {
068        if (jarFile != null) {
069            JarEntry jarEntry = jarFile.getJarEntry(resourceName);
070            if (jarEntry != null) {
071                try {
072                    return new JarResourceHandle(jarFile, jarEntry, getCodeSource());
073                } catch (MalformedURLException e) {
074                    e.printStackTrace();
075                }
076            }
077        } else {
078            try {
079                final JarInputStream is = new JarInputStream(new ByteArrayInputStream(this.content));
080                JarEntry jarEntry;
081                while ((jarEntry = is.getNextJarEntry()) != null) {
082                    if (jarEntry.getName().equals(resourceName)) {
083                        try {
084                            return new JarEntryResourceHandle(jarEntry, is);
085                        } catch (Exception e) {
086                            e.printStackTrace();
087                        }
088                    }
089                }
090            } catch (IOException e) {
091                e.printStackTrace();
092            }
093        }
094        return null;
095    }
096
097    public Manifest getManifest() throws IOException {
098        if (jarFile != null) {
099            return jarFile.getManifest();
100        } else {
101            try {
102                JarInputStream is = new JarInputStream(new ByteArrayInputStream(this.content));
103                return is.getManifest();
104            } catch (IOException e) {
105                e.printStackTrace();
106            }
107        }
108        return null;
109    }
110
111    @Override
112    public void close() {
113        if (jarFile != null) {
114            try {
115                jarFile.close();
116            } catch (Exception ignored) {
117            }
118        }
119    }
120
121    private class JarEntryResourceHandle extends AbstractResourceHandle {
122
123        private final JarEntry jarEntry2;
124        private final JarInputStream is;
125
126        public JarEntryResourceHandle(JarEntry jarEntry2, JarInputStream is) {
127            this.jarEntry2 = jarEntry2;
128            this.is = is;
129        }
130
131        public String getName() {
132            return jarEntry2.getName();
133        }
134
135        public URL getUrl() {
136            try {
137                return new URL("jar", "", -1, getCodeSource() + "!/" + jarEntry2.getName());
138            } catch (MalformedURLException e) {
139                throw new RuntimeException(e);
140            }
141        }
142
143        public boolean isDirectory() {
144            return jarEntry2.isDirectory();
145        }
146
147        public URL getCodeSourceUrl() {
148            return getCodeSource();
149        }
150
151        public InputStream getInputStream() throws IOException {
152            return is;
153        }
154
155        public int getContentLength() {
156            return (int) jarEntry2.getSize();
157        }
158    }
159}