mirror of
https://github.com/square/okhttp.git
synced 2025-07-31 05:04:26 +03:00
Publish OSGi metadata for OkHttp
This commit is contained in:
committed by
Jesse Wilson
parent
f692f07744
commit
b4d66af1da
@ -59,3 +59,4 @@ Committer's Guides
|
|||||||
[releasing]: http://square.github.io/okhttp/releasing/
|
[releasing]: http://square.github.io/okhttp/releasing/
|
||||||
[security]: http://square.github.io/okhttp/security/
|
[security]: http://square.github.io/okhttp/security/
|
||||||
[works_with_okhttp]: http://square.github.io/okhttp/works_with_okhttp/
|
[works_with_okhttp]: http://square.github.io/okhttp/works_with_okhttp/
|
||||||
|
[okhttp_build]: https://github.com/square/okhttp/blob/master/okhttp/build.gradle
|
||||||
|
32
build.gradle
32
build.gradle
@ -1,5 +1,3 @@
|
|||||||
import net.ltgt.gradle.errorprone.CheckSeverity
|
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.versions = [
|
ext.versions = [
|
||||||
'animalSniffer': '1.19',
|
'animalSniffer': '1.19',
|
||||||
@ -20,7 +18,9 @@ buildscript {
|
|||||||
'okio': '2.9.0',
|
'okio': '2.9.0',
|
||||||
'ktlint': '0.38.0',
|
'ktlint': '0.38.0',
|
||||||
'picocli': '4.5.1',
|
'picocli': '4.5.1',
|
||||||
'openjsse': '1.1.0'
|
'openjsse': '1.1.0',
|
||||||
|
'bnd': '5.1.2',
|
||||||
|
'equinox': '3.16.0'
|
||||||
]
|
]
|
||||||
|
|
||||||
ext.deps = [
|
ext.deps = [
|
||||||
@ -43,13 +43,18 @@ buildscript {
|
|||||||
'moshi': "com.squareup.moshi:moshi:${versions.moshi}",
|
'moshi': "com.squareup.moshi:moshi:${versions.moshi}",
|
||||||
'moshiKotlin': "com.squareup.moshi:moshi-kotlin-codegen:${versions.moshi}",
|
'moshiKotlin': "com.squareup.moshi:moshi-kotlin-codegen:${versions.moshi}",
|
||||||
'okio': "com.squareup.okio:okio:${versions.okio}",
|
'okio': "com.squareup.okio:okio:${versions.okio}",
|
||||||
'openjsse': "org.openjsse:openjsse:${versions.openjsse}"
|
'openjsse': "org.openjsse:openjsse:${versions.openjsse}",
|
||||||
|
'bnd': "biz.aQute.bnd:biz.aQute.bnd.gradle:${versions.bnd}",
|
||||||
|
'bndResolve': "biz.aQute.bnd:biz.aQute.resolve:${versions.bnd}",
|
||||||
|
'equinox': "org.eclipse.platform:org.eclipse.osgi:${versions.equinox}",
|
||||||
|
'kotlinStdlibOsgi': "org.jetbrains.kotlin:kotlin-osgi-bundle:${versions.kotlin}"
|
||||||
]
|
]
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10"
|
||||||
classpath "org.jetbrains.dokka:dokka-gradle-plugin:0.10.1"
|
classpath "org.jetbrains.dokka:dokka-gradle-plugin:0.10.1"
|
||||||
classpath "com.android.tools.build:gradle:4.0.1"
|
classpath "com.android.tools.build:gradle:4.0.1"
|
||||||
|
classpath deps.bnd
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
@ -107,6 +112,23 @@ allprojects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ext.applyOsgi = { project ->
|
||||||
|
project.apply plugin: 'biz.aQute.bnd.builder'
|
||||||
|
|
||||||
|
project.sourceSets {
|
||||||
|
osgi
|
||||||
|
}
|
||||||
|
|
||||||
|
project.jar { t ->
|
||||||
|
t.setClasspath(project.sourceSets.osgi['compileClasspath'] + project.sourceSets.main['compileClasspath'])
|
||||||
|
}
|
||||||
|
|
||||||
|
project.dependencies {
|
||||||
|
// The OSGi kotlin-stdlib lets bnd infer bundle versions.
|
||||||
|
osgiApi deps.kotlinStdlibOsgi
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Configure building for Java+Kotlin projects. */
|
/** Configure building for Java+Kotlin projects. */
|
||||||
subprojects { project ->
|
subprojects { project ->
|
||||||
if (project.name == 'android-test') return
|
if (project.name == 'android-test') return
|
||||||
@ -118,6 +140,8 @@ subprojects { project ->
|
|||||||
apply plugin: 'checkstyle'
|
apply plugin: 'checkstyle'
|
||||||
apply plugin: 'ru.vyarus.animalsniffer'
|
apply plugin: 'ru.vyarus.animalsniffer'
|
||||||
apply plugin: 'org.jetbrains.dokka'
|
apply plugin: 'org.jetbrains.dokka'
|
||||||
|
apply plugin: 'biz.aQute.bnd.builder'
|
||||||
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
|
applyOsgi(this)
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
manifest {
|
// MANIFEST.MF, including OSGi bnd instructions.
|
||||||
attributes('Automatic-Module-Name': 'okhttp3.brotli')
|
bnd '''
|
||||||
}
|
Export-Package: okhttp3.brotli
|
||||||
|
Automatic-Module-Name: okhttp3.brotli
|
||||||
|
Bundle-SymbolicName: com.squareup.okhttp3.brotli
|
||||||
|
'''
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
|
applyOsgi(this)
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
manifest {
|
// MANIFEST.MF, including OSGi bnd instructions.
|
||||||
attributes('Automatic-Module-Name': 'okhttp3.dnsoverhttps')
|
bnd '''
|
||||||
}
|
Export-Package: okhttp3.dnsoverhttps
|
||||||
|
Automatic-Module-Name: okhttp3.dnsoverhttps
|
||||||
|
Bundle-SymbolicName: com.squareup.okhttp3.dnsoverhttps
|
||||||
|
'''
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
apply plugin: 'me.champeau.gradle.japicmp'
|
apply plugin: 'me.champeau.gradle.japicmp'
|
||||||
|
applyOsgi(this)
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
manifest {
|
// MANIFEST.MF, including OSGi bnd instructions.
|
||||||
attributes('Automatic-Module-Name': 'okhttp3.logging')
|
bnd '''
|
||||||
}
|
Export-Package: okhttp3.logging
|
||||||
|
Automatic-Module-Name: okhttp3.logging
|
||||||
|
Bundle-SymbolicName: com.squareup.okhttp3.logging
|
||||||
|
'''
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
apply plugin: 'me.champeau.gradle.japicmp'
|
apply plugin: 'me.champeau.gradle.japicmp'
|
||||||
|
applyOsgi(this)
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
manifest {
|
// MANIFEST.MF, including OSGi bnd instructions.
|
||||||
attributes('Automatic-Module-Name': 'okhttp3.sse')
|
bnd '''
|
||||||
}
|
Export-Package: okhttp3.sse
|
||||||
|
Automatic-Module-Name: okhttp3.sse
|
||||||
|
Bundle-SymbolicName: com.squareup.okhttp3.sse
|
||||||
|
'''
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
apply plugin: 'me.champeau.gradle.japicmp'
|
apply plugin: 'me.champeau.gradle.japicmp'
|
||||||
|
applyOsgi(this)
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
manifest {
|
// MANIFEST.MF, including OSGi bnd instructions.
|
||||||
attributes('Automatic-Module-Name': 'okhttp3.tls')
|
bnd '''
|
||||||
}
|
Export-Package: okhttp3.tls
|
||||||
|
Automatic-Module-Name: okhttp3.tls
|
||||||
|
Bundle-SymbolicName: com.squareup.okhttp3.tls
|
||||||
|
'''
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -1,13 +1,20 @@
|
|||||||
apply plugin: 'me.champeau.gradle.japicmp'
|
apply plugin: 'me.champeau.gradle.japicmp'
|
||||||
|
applyOsgi(this)
|
||||||
|
|
||||||
|
def mainProj = project(':okhttp')
|
||||||
jar {
|
jar {
|
||||||
manifest {
|
// MANIFEST.MF, including OSGi bnd instructions.
|
||||||
attributes('Automatic-Module-Name': 'okhttp3.urlconnection')
|
// urlconnection needs to be an OSGi fragment because its package name is the same as okhttp3's.
|
||||||
}
|
bnd """
|
||||||
|
Fragment-Host: com.squareup.okhttp3; bundle-version="\${range;[==,+);\${version_cleanup;${mainProj.version}}}"
|
||||||
|
Automatic-Module-Name: okhttp3.urlconnection
|
||||||
|
Bundle-SymbolicName: com.squareup.okhttp3.urlconnection
|
||||||
|
-removeheaders: Private-Package
|
||||||
|
"""
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api project(':okhttp')
|
api mainProj
|
||||||
compileOnly deps.jsr305
|
compileOnly deps.jsr305
|
||||||
compileOnly deps.animalSniffer
|
compileOnly deps.animalSniffer
|
||||||
|
|
||||||
|
@ -1,9 +1,26 @@
|
|||||||
apply plugin: 'me.champeau.gradle.japicmp'
|
apply plugin: 'me.champeau.gradle.japicmp'
|
||||||
|
applyOsgi(this)
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
manifest {
|
// MANIFEST.MF, including OSGi bnd instructions.
|
||||||
attributes('Automatic-Module-Name': 'okhttp3')
|
// We export okhttp3.internal for our own modules use.
|
||||||
}
|
// The packages of all optional dependencies must be explicitly specified.
|
||||||
|
bnd '''
|
||||||
|
Export-Package: \
|
||||||
|
okhttp3,\
|
||||||
|
okhttp3.internal.*;okhttpinternal=true;mandatory:=okhttpinternal
|
||||||
|
Import-Package: \
|
||||||
|
android.*;resolution:=optional,\
|
||||||
|
com.oracle.svm.core.annotate;resolution:=optional,\
|
||||||
|
dalvik.system;resolution:=optional,\
|
||||||
|
org.conscrypt;resolution:=optional,\
|
||||||
|
org.bouncycastle.*;resolution:=optional,\
|
||||||
|
org.openjsse.*;resolution:=optional,\
|
||||||
|
sun.security.ssl;resolution:=optional,\
|
||||||
|
*
|
||||||
|
Automatic-Module-Name: okhttp3
|
||||||
|
Bundle-SymbolicName: com.squareup.okhttp3
|
||||||
|
'''
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
@ -21,9 +38,21 @@ task copyJavaTemplates(type: Copy) {
|
|||||||
filteringCharset = 'UTF-8'
|
filteringCharset = 'UTF-8'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Expose OSGi jars to the test environment.
|
||||||
|
configurations {
|
||||||
|
osgiTestDeploy
|
||||||
|
}
|
||||||
|
task copyOsgiTestDeployment(type: Copy) {
|
||||||
|
from configurations.osgiTestDeploy
|
||||||
|
into "${buildDir}/resources/test/okhttp3/osgi/deployments"
|
||||||
|
}
|
||||||
|
tasks.test.dependsOn(copyOsgiTestDeployment)
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api deps.okio
|
api deps.okio
|
||||||
api deps.kotlinStdlib
|
api deps.kotlinStdlib
|
||||||
|
|
||||||
|
// These compileOnly dependencies must also be listed in the OSGi configuration above.
|
||||||
compileOnly deps.android
|
compileOnly deps.android
|
||||||
compileOnly deps.bouncycastle
|
compileOnly deps.bouncycastle
|
||||||
compileOnly deps.bouncycastletls
|
compileOnly deps.bouncycastletls
|
||||||
@ -47,10 +76,16 @@ dependencies {
|
|||||||
testImplementation project(':okhttp-urlconnection')
|
testImplementation project(':okhttp-urlconnection')
|
||||||
testImplementation project(':mockwebserver')
|
testImplementation project(':mockwebserver')
|
||||||
testImplementation project(':okhttp-logging-interceptor')
|
testImplementation project(':okhttp-logging-interceptor')
|
||||||
|
testImplementation project(':okhttp-brotli')
|
||||||
|
testImplementation project(':okhttp-dnsoverhttps')
|
||||||
|
testImplementation project(':okhttp-sse')
|
||||||
testImplementation deps.conscrypt
|
testImplementation deps.conscrypt
|
||||||
testImplementation deps.junit
|
testImplementation deps.junit
|
||||||
testImplementation deps.assertj
|
testImplementation deps.assertj
|
||||||
testImplementation deps.openjsse
|
testImplementation deps.openjsse
|
||||||
|
testImplementation deps.bndResolve
|
||||||
|
osgiTestDeploy deps.equinox
|
||||||
|
osgiTestDeploy deps.kotlinStdlibOsgi
|
||||||
testCompileOnly deps.jsr305
|
testCompileOnly deps.jsr305
|
||||||
}
|
}
|
||||||
|
|
||||||
|
159
okhttp/src/test/java/okhttp3/osgi/OsgiTest.java
Normal file
159
okhttp/src/test/java/okhttp3/osgi/OsgiTest.java
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Square, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package okhttp3.osgi;
|
||||||
|
|
||||||
|
import aQute.bnd.build.Project;
|
||||||
|
import aQute.bnd.build.Workspace;
|
||||||
|
import aQute.bnd.build.model.BndEditModel;
|
||||||
|
import aQute.bnd.deployer.repository.LocalIndexedRepo;
|
||||||
|
import aQute.bnd.osgi.Constants;
|
||||||
|
import aQute.bnd.service.RepositoryPlugin;
|
||||||
|
import biz.aQute.resolve.Bndrun;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import okio.BufferedSource;
|
||||||
|
import okio.Okio;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public final class OsgiTest {
|
||||||
|
/** Each is the Bundle-SymbolicName of an OkHttp module's OSGi configuration. */
|
||||||
|
private static final List<String> REQUIRED_BUNDLES = Arrays.asList(
|
||||||
|
"com.squareup.okhttp3",
|
||||||
|
"com.squareup.okhttp3.brotli",
|
||||||
|
"com.squareup.okhttp3.dnsoverhttps",
|
||||||
|
"com.squareup.okhttp3.logging",
|
||||||
|
"com.squareup.okhttp3.sse",
|
||||||
|
"com.squareup.okhttp3.tls",
|
||||||
|
"com.squareup.okhttp3.urlconnection"
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Equinox must also be on the testing classpath. */
|
||||||
|
private static final String RESOLVE_OSGI_FRAMEWORK = "org.eclipse.osgi";
|
||||||
|
private static final String RESOLVE_JAVA_VERSION = "JavaSE-1.8";
|
||||||
|
private static final String REPO_NAME = "OsgiTest";
|
||||||
|
|
||||||
|
private File testResourceDir;
|
||||||
|
private File workspaceDir;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
testResourceDir = new File("./build/resources/test/okhttp3/osgi");
|
||||||
|
workspaceDir = new File(testResourceDir, "workspace");
|
||||||
|
|
||||||
|
// Ensure we start from scratch.
|
||||||
|
deleteDirectory(workspaceDir);
|
||||||
|
workspaceDir.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve the OSGi metadata of the all okhttp3 modules. If required modules do not have OSGi
|
||||||
|
* metadata this will fail with an exception.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testMainModuleWithSiblings() throws Exception {
|
||||||
|
try (Workspace workspace = createWorkspace();
|
||||||
|
Bndrun bndRun = createBndRun(workspace)) {
|
||||||
|
bndRun.resolve(false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Workspace createWorkspace() throws Exception {
|
||||||
|
File bndDir = new File(workspaceDir, "cnf");
|
||||||
|
File repoDir = new File(bndDir, "repo");
|
||||||
|
repoDir.mkdirs();
|
||||||
|
|
||||||
|
Workspace workspace = new Workspace(workspaceDir, bndDir.getName());
|
||||||
|
workspace.setProperty(Constants.PLUGIN + "." + REPO_NAME, ""
|
||||||
|
+ LocalIndexedRepo.class.getName()
|
||||||
|
+ "; " + LocalIndexedRepo.PROP_NAME + " = '" + REPO_NAME + "'"
|
||||||
|
+ "; " + LocalIndexedRepo.PROP_LOCAL_DIR + " = '" + repoDir + "'");
|
||||||
|
workspace.refresh();
|
||||||
|
prepareWorkspace(workspace);
|
||||||
|
return workspace;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void prepareWorkspace(Workspace workspace) throws Exception {
|
||||||
|
RepositoryPlugin repositoryPlugin = workspace.getRepository(REPO_NAME);
|
||||||
|
|
||||||
|
// Deploy the bundles in the deployments test directory.
|
||||||
|
deployDirectory(repositoryPlugin, new File(testResourceDir, "deployments"));
|
||||||
|
deployClassPath(repositoryPlugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Bndrun createBndRun(Workspace workspace) throws Exception {
|
||||||
|
// Creating the run require string. It will always use the latest version of each bundle
|
||||||
|
// available in the repository.
|
||||||
|
String runRequireString = REQUIRED_BUNDLES.stream()
|
||||||
|
.map(s -> "osgi.identity;filter:='(osgi.identity=" + s + ")'")
|
||||||
|
.collect(Collectors.joining(","));
|
||||||
|
|
||||||
|
BndEditModel bndEditModel = new BndEditModel(workspace);
|
||||||
|
// Temporary project to satisfy bnd API.
|
||||||
|
bndEditModel.setProject(new Project(workspace, workspaceDir));
|
||||||
|
|
||||||
|
Bndrun result = new Bndrun(bndEditModel);
|
||||||
|
result.setRunfw(RESOLVE_OSGI_FRAMEWORK);
|
||||||
|
result.setRunee(RESOLVE_JAVA_VERSION);
|
||||||
|
result.setRunRequires(runRequireString);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deployDirectory(RepositoryPlugin repository, File directory) throws Exception {
|
||||||
|
File[] files = directory.listFiles();
|
||||||
|
if (files == null) return;
|
||||||
|
|
||||||
|
for (File file : files) {
|
||||||
|
deployFile(repository, file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deployClassPath(RepositoryPlugin repositoryPlugin) throws Exception {
|
||||||
|
String classpath = System.getProperty("java.class.path");
|
||||||
|
for (String classPathEntry : classpath.split(File.pathSeparator)) {
|
||||||
|
deployFile(repositoryPlugin, new File(classPathEntry));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deployFile(RepositoryPlugin repositoryPlugin, File file) throws Exception {
|
||||||
|
if (!file.exists() || file.isDirectory()) return;
|
||||||
|
|
||||||
|
try (BufferedSource source = Okio.buffer(Okio.source(file))) {
|
||||||
|
repositoryPlugin.put(source.inputStream(), new RepositoryPlugin.PutOptions());
|
||||||
|
System.out.println("Deployed " + file.getName());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
if (e.getMessage().contains("Jar does not have a symbolic name")) {
|
||||||
|
System.out.println("Skipped non-OSGi dependency: " + file.getName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void deleteDirectory(File dir) throws IOException {
|
||||||
|
if (!dir.exists()) return;
|
||||||
|
|
||||||
|
Files.walk(dir.toPath())
|
||||||
|
.filter(Files::isRegularFile)
|
||||||
|
.map(Path::toFile)
|
||||||
|
.forEach(File::delete);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user