This repository has been archived by the owner on Feb 25, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Provide APIs to allow usage of cached ZipFileSystem instances
Added JDK 11's zipfs implementation
- Loading branch information
Showing
24 changed files
with
6,464 additions
and
274 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 2 additions & 3 deletions
5
...n/tools/javac/file/AndroidFsProvider.java → .../androidide/zipfs2/AndroidFsProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
252 changes: 252 additions & 0 deletions
252
src/java.compiler/share/classes/com/itsaky/androidide/zipfs2/ByteArrayChannel.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,252 @@ | ||
/* | ||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. | ||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | ||
* | ||
* This code is free software; you can redistribute it and/or modify it | ||
* under the terms of the GNU General Public License version 2 only, as | ||
* published by the Free Software Foundation. Oracle designates this | ||
* particular file as subject to the "Classpath" exception as provided | ||
* by Oracle in the LICENSE file that accompanied this code. | ||
* | ||
* This code is distributed in the hope that it will be useful, but WITHOUT | ||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
* version 2 for more details (a copy is included in the LICENSE file that | ||
* accompanied this code). | ||
* | ||
* You should have received a copy of the GNU General Public License version | ||
* 2 along with this work; if not, write to the Free Software Foundation, | ||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | ||
* | ||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | ||
* or visit www.oracle.com if you need additional information or have any | ||
* questions. | ||
*/ | ||
|
||
package com.itsaky.androidide.zipfs2; | ||
|
||
import java.io.IOException; | ||
import java.nio.ByteBuffer; | ||
import java.nio.channels.ClosedChannelException; | ||
import java.nio.channels.NonWritableChannelException; | ||
import java.nio.channels.SeekableByteChannel; | ||
import java.util.Arrays; | ||
import java.util.concurrent.locks.ReadWriteLock; | ||
import java.util.concurrent.locks.ReentrantReadWriteLock; | ||
|
||
public class ByteArrayChannel implements SeekableByteChannel { | ||
|
||
private final ReadWriteLock rwlock = new ReentrantReadWriteLock(); | ||
private byte buf[]; | ||
|
||
/* | ||
* The current position of this channel. | ||
*/ | ||
private int pos; | ||
|
||
/* | ||
* The index that is one greater than the last valid byte in the channel. | ||
*/ | ||
private int last; | ||
|
||
private boolean closed; | ||
private boolean readonly; | ||
|
||
/* | ||
* Creates a {@code ByteArrayChannel} with size {@code sz}. | ||
*/ | ||
ByteArrayChannel(int sz, boolean readonly) { | ||
this.buf = new byte[sz]; | ||
this.pos = this.last = 0; | ||
this.readonly = readonly; | ||
} | ||
|
||
/* | ||
* Creates a ByteArrayChannel with its 'pos' at 0 and its 'last' at buf's end. | ||
* Note: no defensive copy of the 'buf', used directly. | ||
*/ | ||
ByteArrayChannel(byte[] buf, boolean readonly) { | ||
this.buf = buf; | ||
this.pos = 0; | ||
this.last = buf.length; | ||
this.readonly = readonly; | ||
} | ||
|
||
@Override | ||
public boolean isOpen() { | ||
return !closed; | ||
} | ||
|
||
@Override | ||
public long position() throws IOException { | ||
beginRead(); | ||
try { | ||
ensureOpen(); | ||
return pos; | ||
} finally { | ||
endRead(); | ||
} | ||
} | ||
|
||
@Override | ||
public SeekableByteChannel position(long pos) throws IOException { | ||
beginWrite(); | ||
try { | ||
ensureOpen(); | ||
if (pos < 0 || pos >= Integer.MAX_VALUE) | ||
throw new IllegalArgumentException("Illegal position " + pos); | ||
this.pos = Math.min((int)pos, last); | ||
return this; | ||
} finally { | ||
endWrite(); | ||
} | ||
} | ||
|
||
@Override | ||
public int read(ByteBuffer dst) throws IOException { | ||
beginWrite(); | ||
try { | ||
ensureOpen(); | ||
if (pos == last) | ||
return -1; | ||
int n = Math.min(dst.remaining(), last - pos); | ||
dst.put(buf, pos, n); | ||
pos += n; | ||
return n; | ||
} finally { | ||
endWrite(); | ||
} | ||
} | ||
|
||
@Override | ||
public SeekableByteChannel truncate(long size) throws IOException { | ||
if (readonly) | ||
throw new NonWritableChannelException(); | ||
ensureOpen(); | ||
throw new UnsupportedOperationException(); | ||
} | ||
|
||
@Override | ||
public int write(ByteBuffer src) throws IOException { | ||
if (readonly) | ||
throw new NonWritableChannelException(); | ||
beginWrite(); | ||
try { | ||
ensureOpen(); | ||
int n = src.remaining(); | ||
ensureCapacity(pos + n); | ||
src.get(buf, pos, n); | ||
pos += n; | ||
if (pos > last) { | ||
last = pos; | ||
} | ||
return n; | ||
} finally { | ||
endWrite(); | ||
} | ||
} | ||
|
||
@Override | ||
public long size() throws IOException { | ||
beginRead(); | ||
try { | ||
ensureOpen(); | ||
return last; | ||
} finally { | ||
endRead(); | ||
} | ||
} | ||
|
||
@Override | ||
public void close() throws IOException { | ||
if (closed) | ||
return; | ||
beginWrite(); | ||
try { | ||
closed = true; | ||
buf = null; | ||
pos = 0; | ||
last = 0; | ||
} finally { | ||
endWrite(); | ||
} | ||
} | ||
|
||
/** | ||
* Creates a newly allocated byte array. Its size is the current | ||
* size of this channel and the valid contents of the buffer | ||
* have been copied into it. | ||
* | ||
* @return the current contents of this channel, as a byte array. | ||
*/ | ||
public byte[] toByteArray() { | ||
beginRead(); | ||
try { | ||
// avoid copy if last == bytes.length? | ||
return Arrays.copyOf(buf, last); | ||
} finally { | ||
endRead(); | ||
} | ||
} | ||
|
||
private void ensureOpen() throws IOException { | ||
if (closed) | ||
throw new ClosedChannelException(); | ||
} | ||
|
||
private final void beginWrite() { | ||
rwlock.writeLock().lock(); | ||
} | ||
|
||
private final void endWrite() { | ||
rwlock.writeLock().unlock(); | ||
} | ||
|
||
private final void beginRead() { | ||
rwlock.readLock().lock(); | ||
} | ||
|
||
private final void endRead() { | ||
rwlock.readLock().unlock(); | ||
} | ||
|
||
private void ensureCapacity(int minCapacity) { | ||
// overflow-conscious code | ||
if (minCapacity - buf.length > 0) { | ||
grow(minCapacity); | ||
} | ||
} | ||
|
||
/** | ||
* The maximum size of array to allocate. | ||
* Some VMs reserve some header words in an array. | ||
* Attempts to allocate larger arrays may result in | ||
* OutOfMemoryError: Requested array size exceeds VM limit | ||
*/ | ||
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; | ||
|
||
/** | ||
* Increases the capacity to ensure that it can hold at least the | ||
* number of elements specified by the minimum capacity argument. | ||
* | ||
* @param minCapacity the desired minimum capacity | ||
*/ | ||
private void grow(int minCapacity) { | ||
// overflow-conscious code | ||
int oldCapacity = buf.length; | ||
int newCapacity = oldCapacity << 1; | ||
if (newCapacity - minCapacity < 0) | ||
newCapacity = minCapacity; | ||
if (newCapacity - MAX_ARRAY_SIZE > 0) | ||
newCapacity = hugeCapacity(minCapacity); | ||
buf = Arrays.copyOf(buf, newCapacity); | ||
} | ||
|
||
private static int hugeCapacity(int minCapacity) { | ||
if (minCapacity < 0) // overflow | ||
throw new OutOfMemoryError(); | ||
return (minCapacity > MAX_ARRAY_SIZE) ? | ||
Integer.MAX_VALUE : | ||
MAX_ARRAY_SIZE; | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
src/java.compiler/share/classes/com/itsaky/androidide/zipfs2/Collections2.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/* | ||
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license | ||
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template | ||
*/ | ||
package com.itsaky.androidide.zipfs2; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.HashSet; | ||
import java.util.List; | ||
import java.util.Set; | ||
|
||
/** | ||
* | ||
* @author itsaky | ||
*/ | ||
public class Collections2 { | ||
|
||
public static <T> List<T> listOf(T... values) { | ||
final List<T> result = new ArrayList<>(); | ||
if (values == null) { | ||
return result; | ||
} | ||
result.addAll(Arrays.asList(values)); | ||
return result; | ||
} | ||
|
||
public static <T> Set<T> setOf(T... values) { | ||
final Set<T> result = new HashSet<>(); | ||
if (values == null) { | ||
return result; | ||
} | ||
result.addAll(Arrays.asList(values)); | ||
return result; | ||
} | ||
} |
75 changes: 75 additions & 0 deletions
75
src/java.compiler/share/classes/com/itsaky/androidide/zipfs2/JarFileSystemProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/* | ||
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. | ||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | ||
* | ||
* This code is free software; you can redistribute it and/or modify it | ||
* under the terms of the GNU General Public License version 2 only, as | ||
* published by the Free Software Foundation. Oracle designates this | ||
* particular file as subject to the "Classpath" exception as provided | ||
* by Oracle in the LICENSE file that accompanied this code. | ||
* | ||
* This code is distributed in the hope that it will be useful, but WITHOUT | ||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
* version 2 for more details (a copy is included in the LICENSE file that | ||
* accompanied this code). | ||
* | ||
* You should have received a copy of the GNU General Public License version | ||
* 2 along with this work; if not, write to the Free Software Foundation, | ||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | ||
* | ||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | ||
* or visit www.oracle.com if you need additional information or have any | ||
* questions. | ||
*/ | ||
|
||
package com.itsaky.androidide.zipfs2; | ||
|
||
import java.net.URI; | ||
import java.net.URISyntaxException; | ||
import java.nio.file.FileSystem; | ||
import java.nio.file.Path; | ||
import java.nio.file.Paths; | ||
|
||
public class JarFileSystemProvider extends ZipFileSystemProvider { | ||
|
||
@Override | ||
public String getScheme() { | ||
return "jar"; | ||
} | ||
|
||
@Override | ||
protected Path uriToPath(URI uri) { | ||
String scheme = uri.getScheme(); | ||
if ((scheme == null) || !scheme.equalsIgnoreCase(getScheme())) { | ||
throw new IllegalArgumentException("URI scheme is not '" + getScheme() + "'"); | ||
} | ||
try { | ||
String uristr = uri.toString(); | ||
int end = uristr.indexOf("!/"); | ||
uristr = uristr.substring(4, (end == -1) ? uristr.length() : end); | ||
uri = new URI(uristr); | ||
return Paths.get(new URI("file", uri.getHost(), uri.getPath(), null)) | ||
.toAbsolutePath(); | ||
} catch (URISyntaxException e) { | ||
throw new AssertionError(e); //never thrown | ||
} | ||
} | ||
|
||
@Override | ||
public Path getPath(URI uri) { | ||
FileSystem fs = getFileSystem(uri); | ||
String path = uri.getFragment(); | ||
if (path == null) { | ||
String uristr = uri.toString(); | ||
int off = uristr.indexOf("!/"); | ||
if (off != -1) | ||
path = uristr.substring(off + 2); | ||
} | ||
if (path != null) | ||
return fs.getPath(path); | ||
throw new IllegalArgumentException("URI: " | ||
+ uri | ||
+ " does not contain path fragment ex. jar:///c:/foo.zip!/BAR"); | ||
} | ||
} |
Oops, something went wrong.