Package aQute.bnd.osgi
Class Jar
java.lang.Object
aQute.bnd.osgi.Jar
- All Implemented Interfaces:
Closeable
,AutoCloseable
-
Nested Class Summary
Nested Classes -
Field Summary
FieldsModifier and TypeFieldDescriptionprivate String[]
private static final Pattern
private static final int
private boolean
private boolean
private Jar.Compression
private static final Pattern
private static final String
private final NavigableMap<String,
Map<String, Resource>> private boolean
static final Object[]
private static final byte[]
Unfortunately we have to write our own manifest :-( because of a stupid bug in the manifest code.private int
private long
private String
private boolean
private String
private Optional<ModuleAttribute>
private String
private boolean
private boolean
private final NavigableMap<String,
Resource> private static final byte[]
private SHA256
private static final Pattern
private File
private static final long
Note that setting the January 1st 1980 (or even worse, "0", as time) won't work due to Java 8 doing some interesting time processing: It checks if this date is before January 1st 1980 and if it is it starts setting some extra fields in the zip.private ZipFile
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionboolean
boolean
addAll
(Jar sub, Instruction filter) Add all the resources in the given jar that match the given filter.boolean
addAll
(Jar sub, Instruction filter, String destination) Add all the resources in the given jar that match the given filter.boolean
addDirectory
(Map<String, Resource> directory, boolean overwrite) private static void
attributes
(Attributes value, OutputStream out) Output an Attributes map.(package private) String
private Jar
buildFromDirectory
(Path baseDir, Pattern doNotCopy) private Jar
private Jar
buildFromResource
(Resource resource) private Jar
buildFromZip
(File file) void
calcChecksums
(String[] algorithms) Calculate the checksums and set them in the manifest.(package private) void
check()
private static String
private static Manifest
void
close()
void
private void
copyResource
(File dir, String path, Resource resource) (package private) void
createDirectories
(Set<String> directories, ZipOutputStream zip, String name) void
doChecksums
(OutputStream out) private void
doManifest
(ZipOutputStream jout, Set<String> directories, String manifestName) void
Make sure we have a manifestboolean
void
Expand the JAR file to a directory.static Jar
fromResource
(String name, Resource resource) getBsn()
Get the jar bsn from theConstants.BUNDLE_SYMBOLICNAME
manifest header.getDataURI
(String path, String mime, int max) Return a data uri from the JAR.getDirectory
(String path) int
Get the length of the last written file or -1 if unavailable.getName()
private static String
Make the JAR file name the project name if we get a src or bin directory.private String
getResource
(String path) getResourceNames
(Predicate<String> matches) getResources
(Resource jarResource, Predicate<String> filter) getResources
(Predicate<String> matches) Optional<byte[]>
Get the SHA256 digest of the last write operation whensetCalculateFileDigest(boolean)
was on.byte[]
Get the jar version from theConstants.BUNDLE_VERSION
manifest header.boolean
hasDirectory
(String path) boolean
isEmpty()
boolean
Answer if the manifest was the first entryboolean
long
(package private) String
manifest()
(package private) Optional<ModuleAttribute>
static void
outputManifest
(Manifest manifest, OutputStream out) Main function to output a manifest properly in UTF-8.private String
private void
putEntry
(ZipOutputStream jout, ZipEntry entry, Resource r) boolean
putResource
(String path, Resource resource) boolean
putResource
(String path, Resource resource, boolean overwrite) void
removePrefix
(String prefixLow) void
removeSubDirs
(String dir) boolean
setCalculateFileDigest
(boolean onOrOff) Make this jar calculate the SHA256 when it is saved as a file.void
setCompression
(Jar.Compression compression) void
setDigestAlgorithms
(String[] algorithms) void
Make sure nobody touches the manifest! If the bundle is signed, we do not want anybody to touch the manifest after the digests have been calculated.void
setManifest
(File file) void
setManifest
(Manifest manifest) void
setManifestName
(String manifestName) void
void
setReproducible
(boolean reproducible) void
toString()
void
updateModified
(long time, String reason) void
void
write
(OutputStream to) private static int
write
(OutputStream out, int width, byte[] bytes) Write the bytes but ensure that the line length does not exceed 72 characters.private static int
write
(OutputStream out, int width, String s) Convert a string to bytes with UTF-8 and then output in max 72 bytesvoid
private static void
writeEntry
(OutputStream out, String name, String value) Write out an entry, handling proper unicode and line length constraintsvoid
writeFolder
(File dir) void
Cleanup the manifest for writing.static void
writeManifest
(Manifest manifest, OutputStream out) private void
writeResource
(ZipOutputStream jout, Set<String> directories, String path, Resource resource)
-
Field Details
-
BUFFER_SIZE
private static final int BUFFER_SIZE- See Also:
-
ZIP_ENTRY_CONSTANT_TIME
private static final long ZIP_ENTRY_CONSTANT_TIMENote that setting the January 1st 1980 (or even worse, "0", as time) won't work due to Java 8 doing some interesting time processing: It checks if this date is before January 1st 1980 and if it is it starts setting some extra fields in the zip. Java 7 does not do that - but in the zip not the milliseconds are saved but values for each of the date fields - but no time zone. And 1980 is the first year which can be saved. If you use January 1st 1980 then it is treated as a special flag in Java 8. Moreover, only even seconds can be stored in the zip file. Java 8 uses the upper half of some other long to store the remaining millis while Java 7 doesn't do that. So make sure that your seconds are even. Moreover, parsing happens via `new Date(millis)` inZipUtils
#javaToDosTime() so we must use default timezone and locale. The date is 1980 February 1st CET. -
DEFAULT_MANIFEST_NAME
- See Also:
-
DEFAULT_DO_NOT_COPY
-
EMPTY_ARRAY
-
resources
-
directories
-
manifest
-
moduleAttribute
-
manifestFirst
private boolean manifestFirst -
manifestName
-
name
-
source
-
zipFile
-
lastModified
private long lastModified -
lastModifiedReason
-
doNotTouchManifest
private boolean doNotTouchManifest -
nomanifest
private boolean nomanifest -
reproducible
private boolean reproducible -
compression
-
closed
private boolean closed -
algorithms
-
sha256
-
calculateFileDigest
private boolean calculateFileDigest -
fileLength
private int fileLength -
EOL
private static final byte[] EOLUnfortunately we have to write our own manifest :-( because of a stupid bug in the manifest code. It tries to handle UTF-8 but the way it does it it makes the bytes platform dependent. So the following code outputs the manifest. A Manifest consists of'Manifest-Version: 1.0\r\n' main-attributes * \r\n name-section main-attributes ::= attributes attributes ::= key ': ' value '\r\n' name-section ::= 'Name: ' name '\r\n' attributes
Lines in the manifest should not exceed 72 bytes (! this is where the manifest screwed up as well when 16 bit unicodes were used).As a bonus, we can now sort the manifest!
-
SEPARATOR
private static final byte[] SEPARATOR -
BSN
-
SIGNER_FILES_P
-
pomXmlFilter
-
-
Constructor Details
-
Jar
-
Jar
- Throws:
IOException
-
Jar
- Throws:
IOException
-
Jar
- Throws:
IOException
-
Jar
- Throws:
IOException
-
Jar
- Throws:
IOException
-
Jar
- Throws:
IOException
-
-
Method Details
-
fromResource
- Throws:
Exception
-
getResources
public static Stream<Resource> getResources(Resource jarResource, Predicate<String> filter) throws Exception - Throws:
Exception
-
getName
Make the JAR file name the project name if we get a src or bin directory.- Parameters:
f
-
-
buildFromDirectory
- Throws:
IOException
-
buildFromZip
- Throws:
IOException
-
buildFromResource
- Throws:
Exception
-
buildFromInputStream
- Throws:
IOException
-
setName
-
toString
-
putResource
-
putResource
-
getResource
-
getResourceNames
-
getResources
-
getParent
-
getDirectories
-
getDirectory
-
getResources
-
addDirectory
-
getManifest
- Throws:
Exception
-
manifest
-
moduleAttribute
- Throws:
Exception
-
getModuleName
- Throws:
Exception
-
automaticModuleName
String automaticModuleName() -
getModuleVersion
- Throws:
Exception
-
exists
-
isEmpty
public boolean isEmpty() -
setManifest
-
setManifest
- Throws:
IOException
-
setManifestName
-
write
- Throws:
Exception
-
write
- Throws:
Exception
-
write
- Throws:
Exception
-
writeFolder
- Throws:
Exception
-
copyResource
- Throws:
Exception
-
doChecksums
- Throws:
Exception
-
padString
-
doManifest
private void doManifest(ZipOutputStream jout, Set<String> directories, String manifestName) throws Exception - Throws:
Exception
-
putEntry
- Throws:
Exception
-
writeManifest
Cleanup the manifest for writing. Cleaning up consists of adding a space after any \n to prevent the manifest to see this newline as a delimiter.- Parameters:
out
- Output- Throws:
IOException
Exception
-
writeManifest
- Throws:
IOException
-
outputManifest
Main function to output a manifest properly in UTF-8.- Parameters:
manifest
- The manifest to outputout
- The output stream- Throws:
IOException
- when something fails
-
writeEntry
Write out an entry, handling proper unicode and line length constraints- Throws:
IOException
-
write
Convert a string to bytes with UTF-8 and then output in max 72 bytes- Parameters:
out
- the output stringwidth
- the current widths
- the string to output- Returns:
- the new width
- Throws:
IOException
- when something fails
-
write
Write the bytes but ensure that the line length does not exceed 72 characters. If it is more than 70 characters, we just put a cr/lf + space.- Parameters:
out
- The output streamwidth
- The nr of characters output in a line before this method startedbytes
- the bytes to output- Returns:
- the nr of characters in the last line
- Throws:
IOException
- if something fails
-
attributes
Output an Attributes map. We will sort this map before outputing.- Parameters:
value
- the attributesout
- the output stream- Throws:
IOException
- when something fails
-
clean
-
clean
-
writeResource
private void writeResource(ZipOutputStream jout, Set<String> directories, String path, Resource resource) throws Exception - Throws:
Exception
-
createDirectories
void createDirectories(Set<String> directories, ZipOutputStream zip, String name) throws IOException - Throws:
IOException
-
getName
-
addAll
Add all the resources in the given jar that match the given filter.- Parameters:
sub
- the jarfilter
- a pattern that should match the resoures in sub to be added
-
addAll
Add all the resources in the given jar that match the given filter.- Parameters:
sub
- the jarfilter
- a pattern that should match the resoures in sub to be added
-
close
public void close()- Specified by:
close
in interfaceAutoCloseable
- Specified by:
close
in interfaceCloseable
-
lastModified
public long lastModified() -
lastModifiedReason
String lastModifiedReason() -
updateModified
-
hasDirectory
-
getPackages
-
getSource
-
addAll
-
rename
-
remove
-
setDoNotTouchManifest
public void setDoNotTouchManifest()Make sure nobody touches the manifest! If the bundle is signed, we do not want anybody to touch the manifest after the digests have been calculated. -
calcChecksums
Calculate the checksums and set them in the manifest.- Throws:
Exception
-
getBsn
Get the jar bsn from theConstants.BUNDLE_SYMBOLICNAME
manifest header.- Returns:
- null when the jar has no manifest, when the manifest has no
Constants.BUNDLE_SYMBOLICNAME
header, or when the value of the header is not a valid bsn according toBSN
. - Throws:
Exception
- when the jar is closed or when the manifest could not be retrieved.
-
getVersion
Get the jar version from theConstants.BUNDLE_VERSION
manifest header.- Returns:
- null when the jar has no manifest or when the manifest has no
Constants.BUNDLE_VERSION
header - Throws:
Exception
- when the jar is closed or when the manifest could not be retrieved.
-
expand
Expand the JAR file to a directory.- Parameters:
dir
- the dst directory, is not required to exist- Throws:
Exception
- if anything does not work as expected.
-
ensureManifest
Make sure we have a manifest- Throws:
Exception
-
isManifestFirst
public boolean isManifestFirst()Answer if the manifest was the first entry -
isReproducible
public boolean isReproducible() -
setReproducible
public void setReproducible(boolean reproducible) -
copy
-
setCompression
-
hasCompression
-
check
void check() -
getDataURI
Return a data uri from the JAR. The data must be less than 32k- Parameters:
path
- the path in the jarmime
- the mime type- Returns:
- a URI or null if conversion could not take place
- Throws:
Exception
-
setDigestAlgorithms
-
getTimelessDigest
- Throws:
Exception
-
stripSignatures
public void stripSignatures() -
removePrefix
-
removeSubDirs
-
getPomXmlResources
-
setCalculateFileDigest
Make this jar calculate the SHA256 when it is saved as a file. When this JAR is written, the digest is always cleared. If this flag is on, it will be calculated and set when the file is successfully saved.- Parameters:
onOrOff
- state of calculating the digest when writing this jar. true is on, otherwise off
-
getSHA256
Get the SHA256 digest of the last write operation whensetCalculateFileDigest(boolean)
was on.- Returns:
- the SHA 256 digest or empty
-
getLength
public int getLength()Get the length of the last written file or -1 if unavailable. The length is only calculated when the checksum calculation was on during the write.- Returns:
- the length of the last written file or -1 if unavailable.
-