-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #667 from bci-oss/474-resolve-from-github
Enable loading model with references from GitHub
- Loading branch information
Showing
52 changed files
with
1,520 additions
and
375 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
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
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
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
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
88 changes: 88 additions & 0 deletions
88
...-aspect-meta-model-java/src/main/java/org/eclipse/esmf/aspectmodel/resolver/Download.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,88 @@ | ||
/* | ||
* Copyright (c) 2024 Robert Bosch Manufacturing Solutions GmbH | ||
* | ||
* See the AUTHORS file(s) distributed with this work for additional | ||
* information regarding authorship. | ||
* | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
* | ||
* SPDX-License-Identifier: MPL-2.0 | ||
*/ | ||
|
||
package org.eclipse.esmf.aspectmodel.resolver; | ||
|
||
import java.io.File; | ||
import java.io.FileOutputStream; | ||
import java.io.IOException; | ||
import java.net.URISyntaxException; | ||
import java.net.URL; | ||
import java.net.http.HttpClient; | ||
import java.net.http.HttpRequest; | ||
import java.net.http.HttpResponse; | ||
import java.time.Duration; | ||
import java.util.Optional; | ||
|
||
import org.eclipse.esmf.aspectmodel.resolver.exceptions.ModelResolutionException; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
/** | ||
* Convenience class to download a file via HTTP, which the ability to auto-detect and use proxy settings | ||
*/ | ||
public class Download { | ||
private static final Logger LOG = LoggerFactory.getLogger( Download.class ); | ||
private final ProxyConfig proxyConfig; | ||
|
||
public Download( final ProxyConfig proxyConfig ) { | ||
this.proxyConfig = proxyConfig; | ||
} | ||
|
||
public Download() { | ||
this( ProxyConfig.detectProxySettings() ); | ||
} | ||
|
||
/** | ||
* Download the file and return the contents as byte array | ||
* | ||
* @param fileUrl the URL | ||
* @return the file contents | ||
*/ | ||
public byte[] downloadFile( final URL fileUrl ) { | ||
try { | ||
final HttpClient.Builder clientBuilder = HttpClient.newBuilder() | ||
.version( HttpClient.Version.HTTP_1_1 ) | ||
.followRedirects( HttpClient.Redirect.ALWAYS ) | ||
.connectTimeout( Duration.ofSeconds( 10 ) ); | ||
Optional.ofNullable( proxyConfig.proxy() ).ifPresent( clientBuilder::proxy ); | ||
Optional.ofNullable( proxyConfig.authenticator() ).ifPresent( clientBuilder::authenticator ); | ||
final HttpClient client = clientBuilder.build(); | ||
final HttpRequest request = HttpRequest.newBuilder().uri( fileUrl.toURI() ).build(); | ||
final HttpResponse<byte[]> response = client.send( request, HttpResponse.BodyHandlers.ofByteArray() ); | ||
return response.body(); | ||
} catch ( final InterruptedException | URISyntaxException | IOException exception ) { | ||
throw new ModelResolutionException( "Could not retrieve " + fileUrl, exception ); | ||
} | ||
} | ||
|
||
/** | ||
* Download the file and write it to the file system | ||
* | ||
* @param fileUrl the URL | ||
* @param outputFile the output file to write | ||
* @return the file written | ||
*/ | ||
public File downloadFile( final URL fileUrl, final File outputFile ) { | ||
try ( final FileOutputStream outputStream = new FileOutputStream( outputFile ) ) { | ||
final byte[] fileContent = downloadFile( fileUrl ); | ||
outputStream.write( fileContent ); | ||
} catch ( final IOException exception ) { | ||
throw new ModelResolutionException( "Could not write file " + outputFile, exception ); | ||
} | ||
|
||
LOG.info( "Downloaded {} to local file {}", fileUrl.getPath(), outputFile ); | ||
return outputFile; | ||
} | ||
} |
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
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
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
103 changes: 103 additions & 0 deletions
103
...ta-model-java/src/main/java/org/eclipse/esmf/aspectmodel/resolver/GitHubFileLocation.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,103 @@ | ||
/* | ||
* Copyright (c) 2024 Robert Bosch Manufacturing Solutions GmbH | ||
* | ||
* See the AUTHORS file(s) distributed with this work for additional | ||
* information regarding authorship. | ||
* | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
* | ||
* SPDX-License-Identifier: MPL-2.0 | ||
*/ | ||
|
||
package org.eclipse.esmf.aspectmodel.resolver; | ||
|
||
import java.io.Serial; | ||
import java.util.Arrays; | ||
import java.util.Optional; | ||
import java.util.function.Supplier; | ||
|
||
import io.vavr.control.Try; | ||
|
||
public record GitHubFileLocation( | ||
GithubRepository repositoryLocation, | ||
String directory, | ||
String namespaceMainPart, | ||
String version, | ||
String filename | ||
) { | ||
public static Optional<GitHubFileLocation> parse( final String url ) { | ||
return Try.of( () -> new GitHubUrlParser( url ).get() ).toJavaOptional(); | ||
} | ||
|
||
private static class ParsingException extends RuntimeException { | ||
@Serial | ||
private static final long serialVersionUID = -4855068216382713797L; | ||
} | ||
|
||
private static class GitHubUrlParser implements Supplier<GitHubFileLocation> { | ||
private int index = 0; | ||
private final String source; | ||
|
||
private GitHubUrlParser( final String source ) { | ||
this.source = source; | ||
} | ||
|
||
private String readSection() { | ||
final int oldIndex = index; | ||
while ( index < source.length() && source.charAt( index ) != '/' ) { | ||
index++; | ||
} | ||
if ( source.charAt( index ) != '/' ) { | ||
throw new ParsingException(); | ||
} | ||
final String result = source.substring( oldIndex, index ); | ||
index++; // eat the slash | ||
return result; | ||
} | ||
|
||
private void eatToken( final String token ) { | ||
if ( source.startsWith( token, index ) ) { | ||
index += token.length(); | ||
return; | ||
} | ||
throw new ParsingException(); | ||
} | ||
|
||
@Override | ||
public GitHubFileLocation get() { | ||
eatToken( "https://" ); | ||
final String host = readSection(); | ||
final String owner = readSection(); | ||
final String repository = readSection(); | ||
final GithubRepository.Ref ref; | ||
if ( source.substring( index ).startsWith( "blob" ) ) { | ||
eatToken( "blob/" ); | ||
final String blob = readSection(); | ||
ref = blob.matches( "[vV]?\\d+\\.\\d+.*" ) | ||
? new GithubRepository.Tag( blob ) | ||
: new GithubRepository.Branch( blob ); | ||
} else { | ||
eatToken( "raw/refs/" ); | ||
if ( source.substring( index ).startsWith( "heads" ) ) { | ||
eatToken( "heads/" ); | ||
final String branchName = readSection(); | ||
ref = new GithubRepository.Branch( branchName ); | ||
} else { | ||
eatToken( "tags/" ); | ||
final String tag = readSection(); | ||
ref = new GithubRepository.Tag( tag ); | ||
} | ||
} | ||
final String rest = source.substring( index ); | ||
final String[] parts = rest.split( "/" ); | ||
final String fileName = parts[parts.length - 1]; | ||
final String version = parts[parts.length - 2]; | ||
final String namespaceMainPart = parts[parts.length - 3]; | ||
final String directory = String.join( "/", Arrays.copyOfRange( parts, 0, parts.length - 3 ) ); | ||
final GithubRepository repoLocation = new GithubRepository( host, owner, repository, ref ); | ||
return new GitHubFileLocation( repoLocation, directory, namespaceMainPart, version, fileName ); | ||
} | ||
} | ||
} |
Oops, something went wrong.