This commit is contained in:
Grahame Grieve 2020-06-05 05:36:14 +10:00
commit 3c296b3ff7
28 changed files with 908 additions and 751 deletions

View File

@ -10,11 +10,11 @@ pr:
strategy:
matrix:
linux:
imageName: "ubuntu-16.04"
# mac:
# imageName: "macos-10.14"
# windows:
# imageName: "vs2017-win2016"
imageName: 'ubuntu-latest'
mac:
imageName: "macos-10.15"
windows:
imageName: "windows-2019"
maxParallel: 3
pool:
@ -26,11 +26,10 @@ variables:
VERSION:
steps:
- bash: ls -la
- bash: pwd
# This task pulls the <version> value from the org.hl7.fhir.r5 project pom.xml file. All modules are released as
# the same version, at the same time, as defined in the root level pom.xml.
- task: PowerShell@2
condition: and(eq(variables.currentImage, 'ubuntu-latest'), eq(variables['Build.SourceBranch'], 'refs/heads/release'))
inputs:
targetType: 'inline'
script: |
@ -42,6 +41,7 @@ steps:
# Prints out the build version, for debugging purposes
- bash: echo Pulled version from pom.xml => $(version)
condition: and(eq(variables.currentImage, 'ubuntu-latest'), eq(variables['Build.SourceBranch'], 'refs/heads/release'))
# Azure pipelines cannot pass variables between pipelines, but it can pass files, so we
# pass the build id (ex: 1.1.13-SNAPSHOT) as a string in a file.
@ -51,12 +51,12 @@ steps:
echo $(version)
VERSION=$(version)
echo "$VERSION" > $(System.DefaultWorkingDirectory)/VERSION
condition: and(eq(variables.currentImage, 'ubuntu-16.04'), eq(variables['Build.SourceBranch'], 'refs/heads/release'))
condition: and(eq(variables.currentImage, 'ubuntu-latest'), eq(variables['Build.SourceBranch'], 'refs/heads/release'))
# Copies the VERSION file containing the build id (ex: 1.1.13-SNAPSHOT) to the staging directory
# This is done for release versions only.
- task: CopyFiles@2
condition: and(eq(variables.currentImage, 'ubuntu-16.04'), eq(variables['Build.SourceBranch'], 'refs/heads/release'))
condition: and(eq(variables.currentImage, 'ubuntu-latest'), eq(variables['Build.SourceBranch'], 'refs/heads/release'))
displayName: 'Copy Files to: $(build.artifactstagingdirectory)'
inputs:
SourceFolder: '$(System.Defaultworkingdirectory)'
@ -73,12 +73,12 @@ steps:
jdkArchitectureOption: 'x64'
publishJUnitResults: true
testResultsFiles: '**/surefire-reports/TEST-*.xml'
goals: 'clean package'
goals: 'package'
# Upload test results to codecov
- script: bash <(curl https://codecov.io/bash) -t $(codecov)
displayName: 'codecov Bash Uploader'
condition: and(eq(variables.currentImage, 'ubuntu-16.04'), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
condition: and(eq(variables.currentImage, 'ubuntu-latest'), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
# Publishes the test results to build artifacts.
- task: PublishCodeCoverageResults@1
@ -87,12 +87,12 @@ steps:
codeCoverageTool: 'JaCoCo'
summaryFileLocation: '$(System.DefaultWorkingDirectory)/org.hl7.fhir.report/target/site/jacoco-aggregate/jacoco.xml'
reportDirectory: '$(System.DefaultWorkingDirectory)/org.hl7.fhir.report/target/site/jacoco-aggregate/'
condition: and(eq(variables.currentImage, 'ubuntu-16.04'), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
condition: and(eq(variables.currentImage, 'ubuntu-latest'), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
# Publishes the built Validator jar to build artifacts. Primarily for testing and debugging builds.
- task: PublishPipelineArtifact@1
displayName: 'Publish Validator jar'
condition: and(eq(variables.currentImage, 'ubuntu-16.04'), eq(variables['Build.SourceBranch'], 'refs/heads/release'))
condition: and(eq(variables.currentImage, 'ubuntu-latest'), eq(variables['Build.SourceBranch'], 'refs/heads/release'))
inputs:
targetPath: "$(System.DefaultWorkingDirectory)/org.hl7.fhir.validation/target/org.hl7.fhir.validation-$(version).jar"
artifactName: Validator
@ -102,7 +102,7 @@ steps:
# for each of the three release pipelines will cause conflicts.
# This is done for release versions only.
- task: PublishBuildArtifacts@1
condition: and(eq(variables.currentImage, 'ubuntu-16.04'), eq(variables['Build.SourceBranch'], 'refs/heads/release'))
condition: and(eq(variables.currentImage, 'ubuntu-latest'), eq(variables['Build.SourceBranch'], 'refs/heads/release'))
displayName: 'Publish Build Artifacts'
inputs:
PathtoPublish: '$(build.artifactstagingdirectory)'

View File

@ -62,7 +62,7 @@ import org.hl7.fhir.r4.utils.NPMPackageGenerator;
import org.hl7.fhir.r4.utils.NPMPackageGenerator.Category;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.cache.NpmPackage;
import org.hl7.fhir.utilities.cache.PackageCacheManager;
import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
import org.hl7.fhir.utilities.cache.PackageGenerator.PackageType;
import org.hl7.fhir.utilities.cache.ToolsVersion;
@ -392,7 +392,7 @@ public class ExtensionDefinitionGenerator {
private List<StructureDefinition> loadSource() throws IOException, FHIRException {
List<StructureDefinition> list = new ArrayList<>();
PackageCacheManager pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
FilesystemPackageCacheManager pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
NpmPackage npm = pcm.loadPackage("hl7.fhir.core", sourceVersion.toCode());
if (sourceVersion == FHIRVersion._4_0_0)
context = SimpleWorkerContext.fromPackage(npm);

View File

@ -44,15 +44,13 @@ import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.commons.codec.binary.Base64;
import org.fhir.ucum.UcumEssenceService;
import org.fhir.ucum.UcumException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r4.context.IWorkerContext;
import org.hl7.fhir.r4.context.SimpleWorkerContext;
import org.hl7.fhir.r4.model.Parameters;
import org.hl7.fhir.utilities.CSFile;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.cache.PackageCacheManager;
import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
import org.hl7.fhir.utilities.cache.ToolsVersion;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@ -73,9 +71,9 @@ public class TestingUtilities {
public static IWorkerContext context() {
if (fcontext == null) {
PackageCacheManager pcm;
FilesystemPackageCacheManager pcm;
try {
pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
fcontext = SimpleWorkerContext.fromPackage(pcm.loadPackage("hl7.fhir.core", "4.0.0"));
fcontext.setUcumService(new UcumEssenceService(TestingUtilities.resourceNameToFile("ucum", "ucum-essence.xml")));
fcontext.setExpansionProfile(new Parameters());

View File

@ -8,7 +8,7 @@ import org.hl7.fhir.r4.elementmodel.Element;
import org.hl7.fhir.r4.elementmodel.Manager;
import org.hl7.fhir.r4.elementmodel.Manager.FhirFormat;
import org.hl7.fhir.r4.formats.IParser.OutputStyle;
import org.hl7.fhir.utilities.cache.PackageCacheManager;
import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
import org.hl7.fhir.utilities.cache.ToolsVersion;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
@ -29,7 +29,7 @@ public class CDARoundTripTests {
@BeforeAll
public void setUp() throws Exception {
context = new SimpleWorkerContext();
PackageCacheManager pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
FilesystemPackageCacheManager pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
context.loadFromPackage(pcm.loadPackage("hl7.fhir.core", "current"), null, "StructureDefinition");
context.loadFromPackage(pcm.loadPackage("hl7.fhir.cda", "current"), null, "StructureDefinition");
}

View File

@ -14,7 +14,7 @@ import org.hl7.fhir.r4.utils.StructureMapUtilities;
import org.hl7.fhir.r4.utils.StructureMapUtilities.ITransformerServices;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.cache.PackageCacheManager;
import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
import org.hl7.fhir.utilities.cache.ToolsVersion;
import org.hl7.fhir.utilities.xml.XMLUtil;
import org.junit.jupiter.api.BeforeAll;
@ -61,7 +61,7 @@ public class FHIRMappingLanguageTests implements ITransformerServices {
@BeforeAll
static public void setUp() throws Exception {
if (context == null) {
PackageCacheManager pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
FilesystemPackageCacheManager pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
context = SimpleWorkerContext.fromPackage(pcm.loadPackage("hl7.fhir.core", "4.0.0"));
jsonParser = new JsonParser();
jsonParser.setOutputStyle(OutputStyle.PRETTY);

View File

@ -18,12 +18,11 @@ import org.fhir.ucum.UcumEssenceService;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.context.SimpleWorkerContext;
import org.hl7.fhir.r5.model.Parameters;
import org.hl7.fhir.r5.terminologies.TerminologyClientR5;
import org.hl7.fhir.utilities.CSFile;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.cache.PackageCacheManager;
import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
import org.hl7.fhir.utilities.cache.ToolsVersion;
import org.hl7.fhir.utilities.tests.BaseTestingUtilities;
import org.w3c.dom.Document;
@ -83,9 +82,9 @@ public class TestingUtilities extends BaseTestingUtilities {
fcontexts = new HashMap<>();
}
if (!fcontexts.containsKey(v)) {
PackageCacheManager pcm;
FilesystemPackageCacheManager pcm;
try {
pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
IWorkerContext fcontext = SimpleWorkerContext.fromPackage(pcm.loadPackage(VersionUtilities.packageForVersion(version), version));
fcontext.setUcumService(new UcumEssenceService(TestingUtilities.loadTestResourceStream("ucum", "ucum-essence.xml")));
fcontext.setExpansionProfile(new Parameters());

View File

@ -9,7 +9,7 @@ import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat;
import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.test.utils.TestingUtilities;
import org.hl7.fhir.r5.utils.FHIRPathEngine;
import org.hl7.fhir.utilities.cache.PackageCacheManager;
import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
import org.hl7.fhir.utilities.cache.ToolsVersion;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
@ -175,7 +175,7 @@ public class CDARoundTripTests {
@Test
public void testSimple() throws IOException {
PackageCacheManager pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
FilesystemPackageCacheManager pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
SimpleWorkerContext context = SimpleWorkerContext.fromPackage(pcm.loadPackage("hl7.fhir.r4.core", "4.0.1"));
context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "any.xml"), "any.xml", null);
context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "ii.xml"), "ii.xml", null);

View File

@ -33,7 +33,7 @@ import org.hl7.fhir.r5.utils.StructureMapUtilities;
import org.hl7.fhir.r5.utils.StructureMapUtilities.ITransformerServices;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.cache.PackageCacheManager;
import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
import org.hl7.fhir.utilities.cache.ToolsVersion;
import org.hl7.fhir.utilities.xml.XMLUtil;
import org.junit.jupiter.api.BeforeAll;
@ -67,7 +67,7 @@ public class FHIRMappingLanguageTests implements ITransformerServices {
@BeforeAll
public static void setUp() throws Exception {
PackageCacheManager pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
FilesystemPackageCacheManager pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
context = SimpleWorkerContext.fromPackage(pcm.loadPackage("hl7.fhir.core", "4.0.1"));
jsonParser = new JsonParser();
jsonParser.setOutputStyle(OutputStyle.PRETTY);

View File

@ -43,7 +43,7 @@ import org.hl7.fhir.r5.utils.IResourceValidator;
import org.hl7.fhir.r5.utils.XVerExtensionManager;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.cache.NpmPackage;
import org.hl7.fhir.utilities.cache.PackageCacheManager;
import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
import org.hl7.fhir.utilities.cache.ToolsVersion;
import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
@ -522,7 +522,7 @@ public class SnapShotGenerationTests {
pu.setDebug(test.isDebug());
pu.setIds(test.getSource(), false);
if (!TestingUtilities.context().hasPackage("hl7.fhir.xver-extensions", "0.0.4")) {
NpmPackage npm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION).loadPackage("hl7.fhir.xver-extensions", "0.0.4");
NpmPackage npm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION).loadPackage("hl7.fhir.xver-extensions", "0.0.4");
TestingUtilities.context().loadFromPackage(npm, new TestLoader(new String[]{"StructureDefinition"}), new String[]{"StructureDefinition"});
}
pu.setXver(new XVerExtensionManager(TestingUtilities.context()));

View File

@ -13,7 +13,7 @@ import org.hl7.fhir.r5.model.StructureMap;
import org.hl7.fhir.r5.test.utils.TestingUtilities;
import org.hl7.fhir.r5.utils.StructureMapUtilities;
import org.hl7.fhir.r5.utils.StructureMapUtilities.ITransformerServices;
import org.hl7.fhir.utilities.cache.PackageCacheManager;
import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
import org.hl7.fhir.utilities.cache.ToolsVersion;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
@ -25,7 +25,7 @@ public class StructureMapUtilitiesTest implements ITransformerServices {
// @BeforeAll
static public void setUp() throws Exception {
PackageCacheManager pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
FilesystemPackageCacheManager pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
context = SimpleWorkerContext.fromPackage(pcm.loadPackage("hl7.fhir.core", "4.0.0"));
}

View File

@ -13,7 +13,7 @@ import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.test.utils.TestingUtilities;
import org.hl7.fhir.r5.utils.FHIRPathEngine;
import org.hl7.fhir.utilities.cache.PackageCacheManager;
import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
import org.hl7.fhir.utilities.cache.ToolsVersion;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
@ -25,7 +25,7 @@ public class XmlParserTests {
@BeforeAll
public static void setUp() throws Exception {
PackageCacheManager pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
FilesystemPackageCacheManager pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
context = SimpleWorkerContext.fromPackage(pcm.loadPackage("hl7.fhir.r4.core", "4.0.1"));
fp = new FHIRPathEngine(context);

View File

@ -0,0 +1,158 @@
package org.hl7.fhir.utilities.cache;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.utilities.Utilities;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
public abstract class BasePackageCacheManager implements IPackageCacheManager {
private static final Logger ourLog = LoggerFactory.getLogger(BasePackageCacheManager.class);
private List<String> myPackageServers = new ArrayList<>();
private Function<String, PackageClient> myClientFactory = address -> new CachingPackageClient(address);
/**
* Constructor
*/
public BasePackageCacheManager() {
super();
}
/**
* Provide a new client factory implementation
*/
public void setClientFactory(Function<String, PackageClient> theClientFactory) {
Validate.notNull(theClientFactory, "theClientFactory must not be null");
myClientFactory = theClientFactory;
}
public List<String> getPackageServers() {
return myPackageServers;
}
/**
* Add a package server that can be used to fetch remote packages
*/
public void addPackageServer(@Nonnull String thePackageServer) {
Validate.notBlank(thePackageServer, "thePackageServer must not be null or empty");
if (!myPackageServers.contains(thePackageServer)) {
myPackageServers.add(thePackageServer);
}
}
/**
* Load the latest version of the identified package from the cache - it it exists
*/
public NpmPackage loadPackageFromCacheOnly(String id) throws IOException {
return loadPackageFromCacheOnly(id, null);
}
/**
* Try to load a package from all registered package servers, and return <code>null</code>
* if it can not be found at any of them.
*/
@Nullable
protected InputStreamWithSrc loadFromPackageServer(String id, String version) {
for (String nextPackageServer : getPackageServers()) {
PackageClient packageClient = myClientFactory.apply(nextPackageServer);
try {
if (Utilities.noString(version)) {
version = packageClient.getLatestVersion(id);
}
InputStream stream = packageClient.fetch(id, version);
String url = packageClient.url(id, version);
return new InputStreamWithSrc(stream, url, version);
} catch (IOException e) {
ourLog.info("Failed to resolve package {}#{} from server: {}", id, version, nextPackageServer);
}
}
return null;
}
public abstract NpmPackage loadPackageFromCacheOnly(String id, @Nullable String version) throws IOException;
@Override
public String getPackageUrl(String packageId) throws IOException {
String result = null;
NpmPackage npm = loadPackageFromCacheOnly(packageId);
if (npm != null) {
return npm.canonical();
}
for (String nextPackageServer : getPackageServers()) {
result = getPackageUrl(packageId, nextPackageServer);
if (result != null) {
return result;
}
}
return result;
}
private String getPackageUrl(String packageId, String server) throws IOException {
PackageClient pc = myClientFactory.apply(server);
List<PackageClient.PackageInfo> res = pc.search(packageId, null, null, false);
if (res.size() == 0) {
return null;
} else {
return res.get(0).getUrl();
}
}
@Override
public String getPackageId(String canonicalUrl) throws IOException {
String result = null;
for (String nextPackageServer : getPackageServers()) {
result = getPackageId(canonicalUrl, nextPackageServer);
if (result != null) {
break;
}
}
return result;
}
private String getPackageId(String canonical, String server) throws IOException {
PackageClient pc = myClientFactory.apply(server);
List<PackageClient.PackageInfo> res = pc.search(null, canonical, null, false);
if (res.size() == 0) {
return null;
} else {
// this is driven by HL7 Australia (http://hl7.org.au/fhir/ is the canonical url for the base package, and the root for all the others)
for (PackageClient.PackageInfo pi : res) {
if (canonical.equals(pi.getCanonical())) {
return pi.getId();
}
}
return res.get(0).getId();
}
}
public class InputStreamWithSrc {
public InputStream stream;
public String url;
public String version;
public InputStreamWithSrc(InputStream stream, String url, String version) {
this.stream = stream;
this.url = url;
this.version = version;
}
}
}

View File

@ -0,0 +1,58 @@
package org.hl7.fhir.utilities.cache;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
/**
* Implementation of a package client that keeps a local disk cache of downloaded artifacts
* in order to avoid re-downloading things
*/
public class CachingPackageClient extends PackageClient {
private String cacheFolder;
public CachingPackageClient(String address) {
super(address);
try {
cacheFolder = Utilities.path(System.getProperty("user.home"), ".fhir", "package-client");
Utilities.createDirectory(cacheFolder);
} catch (IOException e) {
}
}
public boolean exists(String id, String ver) throws IOException {
List<PackageInfo> vl = getVersions(id);
for (PackageInfo pi : vl) {
if (ver.equals(pi.getVersion())) {
return true;
}
}
return false;
}
public InputStream fetchCached(String url) throws IOException {
File cacheFile = new File(Utilities.path(cacheFolder, fn(url)));
if (cacheFile.exists()) {
return new FileInputStream(cacheFile);
}
InputStream fetchedPackage = super.fetchCached(url);
TextFile.bytesToFile(TextFile.streamToBytes(fetchedPackage), cacheFile);
return new FileInputStream(cacheFile);
}
public Date getNewPackages(Date lastCalled, List<PackageInfo> updates) {
return null;
}
}

View File

@ -30,9 +30,20 @@ package org.hl7.fhir.utilities.cache;
*/
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import org.apache.commons.io.FileUtils;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.utilities.IniFile;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.cache.NpmPackage.NpmPackageFolder;
import org.hl7.fhir.utilities.json.JSONUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@ -58,31 +69,12 @@ import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import org.apache.commons.io.FileUtils;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.utilities.IniFile;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.cache.NpmPackage.NpmPackageFolder;
import org.hl7.fhir.utilities.cache.PackageCacheManager.BuildRecord;
import org.hl7.fhir.utilities.cache.PackageCacheManager.BuildRecordSorter;
import org.hl7.fhir.utilities.cache.PackageCacheManager.InputStreamWithSrc;
import org.hl7.fhir.utilities.cache.PackageClient.PackageInfo;
import org.hl7.fhir.utilities.json.JSONUtil;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
/**
* Package cache manager
* This is a package cache manager implementation that uses a local disk cache
*
* <p>
* API:
*
* <p>
* constructor
* getPackageUrl
* getPackageId
@ -90,153 +82,30 @@ import com.google.gson.JsonObject;
* addPackageToCache
*
* @author Grahame Grieve
*
*/
public class PackageCacheManager {
public class InputStreamWithSrc {
public InputStream stream;
public String url;
public String version;
public InputStreamWithSrc(InputStream stream, String url, String version) {
this.stream = stream;
this.url = url;
this.version = version;
}
}
public class BuildRecordSorter implements Comparator<BuildRecord> {
@Override
public int compare(BuildRecord arg0, BuildRecord arg1) {
return arg1.date.compareTo(arg0.date);
}
}
public class BuildRecord {
private String url;
private String packageId;
private String repo;
private Date date;
public BuildRecord(String url, String packageId, String repo, Date date) {
super();
this.url = url;
this.packageId = packageId;
this.repo = repo;
this.date = date;
}
public String getUrl() {
return url;
}
public String getPackageId() {
return packageId;
}
public String getRepo() {
return repo;
}
public Date getDate() {
return date;
}
}
/** if you don't provide and implementation of this interface, the PackageCacheManager will use the web directly.
*
* You can use this interface to
* @author graha
*
*/
public interface INetworkServices {
InputStream resolvePackage(String packageId, String version);
}
public class VersionHistory {
private String id;
private String canonical;
private String current;
private Map<String, String> versions = new HashMap<>();
public String getCanonical() {
return canonical;
}
public String getCurrent() {
return current;
}
public Map<String, String> getVersions() {
return versions;
}
public String getId() {
return id;
}
}
public class PackageEntry {
private byte[] bytes;
private String name;
public PackageEntry(String name) {
this.name = name;
}
public PackageEntry(String name, byte[] bytes) {
this.name = name;
this.bytes = bytes;
}
}
public interface CacheLockFunction<T> {
T get() throws IOException;
}
public class CacheLock {
private final File lockFile;
public CacheLock(String name) throws IOException {
this.lockFile = new File(cacheFolder, name + ".lock");
if (!lockFile.isFile()) {
TextFile.stringToFile("", lockFile);
}
}
public <T> T doWithLock(CacheLockFunction<T> f) throws FileNotFoundException, IOException {
try (FileChannel channel = new RandomAccessFile(lockFile, "rw").getChannel()) {
final FileLock fileLock = channel.lock();
T result = null;
try {
result = f.get();
} finally {
fileLock.release();
}
if (!lockFile.delete()) {
lockFile.deleteOnExit();
}
return result;
}
}
}
public class FilesystemPackageCacheManager extends BasePackageCacheManager implements IPackageCacheManager {
public static final String PRIMARY_SERVER = "http://packages.fhir.org";
public static final String SECONDARY_SERVER = "http://packages2.fhir.org/packages";
// private static final String SECONDARY_SERVER = "http://local.fhir.org:960/packages";
public static final String PACKAGE_REGEX = "^[a-z][a-z0-9\\_\\-]*(\\.[a-z0-9\\_\\-]+)+$";
public static final String PACKAGE_VERSION_REGEX = "^[a-z][a-z0-9\\_\\-]*(\\.[a-z0-9\\_\\-]+)+\\#[a-z0-9\\-\\_]+(\\.[a-z0-9\\-\\_]+)*$";
private static final Logger ourLog = LoggerFactory.getLogger(FilesystemPackageCacheManager.class);
private static final String CACHE_VERSION = "3"; // second version - see wiki page
private String cacheFolder;
private boolean progress = true;
private List<NpmPackage> temporaryPackages = new ArrayList<NpmPackage>();
private List<NpmPackage> temporaryPackages = new ArrayList<>();
private boolean buildLoaded = false;
private Map<String, String> ciList = new HashMap<String, String>();
private JsonArray buildInfo;
// private List<String> allUrls;
// private Map<String, VersionHistory> historyCache = new HashMap<>();
/**
* Constructor
*/
public FilesystemPackageCacheManager(boolean userMode, int toolsVersion) throws IOException {
addPackageServer(PRIMARY_SERVER);
addPackageServer(SECONDARY_SERVER);
// ========================= Initialization ============================================================================
public PackageCacheManager(boolean userMode, int toolsVersion) throws IOException {
if (userMode)
cacheFolder = Utilities.path(System.getProperty("user.home"), ".fhir", "packages");
else
@ -259,16 +128,10 @@ public class PackageCacheManager {
}
}
// ========================= Utilities ============================================================================
public String getFolder() {
return cacheFolder;
}
private static String userDir() throws IOException {
return Utilities.path(System.getProperty("user.home"), ".fhir", "packages");
}
private List<String> sorted(String[] keys) {
List<String> names = new ArrayList<String>();
for (String s : keys)
@ -304,8 +167,7 @@ public class PackageCacheManager {
}
return null; // must return something
});
}
else if (!f.getName().equals("packages.ini"))
} else if (!f.getName().equals("packages.ini"))
FileUtils.forceDelete(f);
}
IniFile ini = new IniFile(Utilities.path(cacheFolder, "packages.ini"));
@ -338,83 +200,38 @@ public class PackageCacheManager {
}
}
private String getPackageId(String canonical, String server) throws IOException {
PackageClient pc = new PackageClient(server);
List<PackageInfo> res = pc.search(null, canonical, null, false);
if (res.size() == 0) {
return null;
} else {
// this is driven by HL7 Australia (http://hl7.org.au/fhir/ is the canonical url for the base package, and the root for all the others)
for (PackageInfo pi : res) {
if (canonical.equals(pi.getCanonical())) {
return pi.getId();
}
}
return res.get(0).getId();
}
}
private String getPackageUrl(String packageId, String server) throws IOException {
PackageClient pc = new PackageClient(server);
List<PackageInfo> res = pc.search(packageId, null, null, false);
if (res.size() == 0) {
return null;
} else {
return res.get(0).getUrl();
}
}
private void listSpecs(Map<String, String> specList, String server) throws IOException {
PackageClient pc = new PackageClient(server);
List<PackageInfo> matches = pc.search(null, null, null, false);
for (PackageInfo m : matches) {
CachingPackageClient pc = new CachingPackageClient(server);
List<PackageClient.PackageInfo> matches = pc.search(null, null, null, false);
for (PackageClient.PackageInfo m : matches) {
if (!specList.containsKey(m.getId())) {
specList.put(m.getId(), m.getUrl());
}
}
}
private InputStreamWithSrc loadFromPackageServer(String id, String v) {
PackageClient pc = new PackageClient(PRIMARY_SERVER);
String u = null;
InputStream stream;
try {
if (Utilities.noString(v)) {
v = pc.getLatestVersion(id);
protected InputStreamWithSrc loadFromPackageServer(String id, String version) {
InputStreamWithSrc retVal = super.loadFromPackageServer(id, version);
if (retVal != null) {
return retVal;
}
stream = pc.fetch(id, v);
u = pc.url(id, v);
} catch (IOException e) {
pc = new PackageClient(SECONDARY_SERVER);
try {
if (Utilities.noString(v)) {
v = pc.getLatestVersion(id);
}
stream = pc.fetch(id, v);
u = pc.url(id, v);
} catch (IOException e1) {
// ok, well, we'll try the old way
return fetchTheOldWay(id, v);
}
}
return new InputStreamWithSrc(stream, pc.url(id, v), v);
return fetchTheOldWay(id, version);
}
public String getLatestVersion(String id) throws IOException {
PackageClient pc = new PackageClient(PRIMARY_SERVER);
for (String nextPackageServer : getPackageServers()) {
CachingPackageClient pc = new CachingPackageClient(nextPackageServer);
try {
return pc.getLatestVersion(id);
} catch (IOException e) {
pc = new PackageClient(SECONDARY_SERVER);
try {
return pc.getLatestVersion(id);
} catch (IOException e1) {
ourLog.info("Failed to determine latest version of package {} from server: {}", id, nextPackageServer);
}
}
return fetchVersionTheOldWay(id);
}
}
}
private NpmPackage loadPackageFromFile(String id, String folder) throws IOException {
File f = new File(Utilities.path(folder, id));
@ -431,9 +248,6 @@ public class PackageCacheManager {
return NpmPackage.fromFolder(f.getAbsolutePath());
}
// ========================= Package Mgmt API =======================================================================
/**
* Clear the cache
*
@ -443,6 +257,8 @@ public class PackageCacheManager {
clearCache();
}
// ========================= Utilities ============================================================================
/**
* Remove a particular package from the cache
*
@ -465,20 +281,9 @@ public class PackageCacheManager {
});
}
/**
* Load the latest version of the identified package from the cache - it it exists
*
* @param id
* @return
* @throws IOException
*/
public NpmPackage loadPackageFromCacheOnly(String id) throws IOException {
return loadPackageFromCacheOnly(id, null);
}
/**
* Load the identified package from the cache - it it exists
*
* <p>
* This is for special purpose only (testing, control over speed of loading).
* Generally, use the loadPackage method
*
@ -487,6 +292,7 @@ public class PackageCacheManager {
* @return
* @throws IOException
*/
@Override
public NpmPackage loadPackageFromCacheOnly(String id, String version) throws IOException {
if (!Utilities.noString(version) && version.startsWith("file:")) {
return loadPackageFromFile(id, version.substring(5));
@ -514,14 +320,15 @@ public class PackageCacheManager {
/**
* Add an already fetched package to the cache
*/
public NpmPackage addPackageToCache(String id, String version, InputStream tgz, String sourceDesc) throws IOException {
@Override
public NpmPackage addPackageToCache(String id, String version, InputStream packageTgzInputStream, String sourceDesc) throws IOException {
checkValidVersionString(version, id);
if (progress) {
System.out.println("Installing " + id + "#" + (version == null ? "?" : version) + " to the package cache");
System.out.print(" Fetching:");
}
NpmPackage npm = NpmPackage.fromPackage(tgz, sourceDesc, true);
NpmPackage npm = NpmPackage.fromPackage(packageTgzInputStream, sourceDesc, true);
if (progress) {
System.out.println();
@ -549,7 +356,7 @@ public class PackageCacheManager {
int c = 0;
int size = 0;
for (Entry<String, NpmPackageFolder> e : npm.getFolders().entrySet()) {
String dir = e.getKey().equals("package") ? Utilities.path(packRoot, "package") : Utilities.path(packRoot, "package", e.getKey());;
String dir = e.getKey().equals("package") ? Utilities.path(packRoot, "package") : Utilities.path(packRoot, "package", e.getKey());
if (!(new File(dir).exists()))
Utilities.createDirectory(dir);
for (Entry<String, byte[]> fe : e.getValue().getContent().entrySet()) {
@ -609,35 +416,13 @@ public class PackageCacheManager {
});
}
public String getPackageId(String canonical) throws IOException {
String result = null;
if (result == null) {
result = getPackageId(canonical, PRIMARY_SERVER);
}
if (result == null) {
result = getPackageId(canonical, SECONDARY_SERVER);
}
if (result == null) {
result = getPackageIdFromBuildList(canonical);
}
return result;
}
@Override
public String getPackageUrl(String packageId) throws IOException {
String result = null;
NpmPackage npm = loadPackageFromCacheOnly(packageId);
if (npm != null) {
return npm.canonical();
}
if (result == null) {
getPackageUrl(packageId, PRIMARY_SERVER);
}
if (result == null) {
result = getPackageUrl(packageId, SECONDARY_SERVER);
}
String result = super.getPackageUrl(packageId);
if (result == null) {
result = getPackageUrlFromBuildList(packageId);
}
return result;
}
@ -645,51 +430,47 @@ public class PackageCacheManager {
for (NpmPackage p : temporaryPackages) {
specList.put(p.name(), p.canonical());
}
listSpecs(specList, PRIMARY_SERVER);
listSpecs(specList, SECONDARY_SERVER);
for (String next : getPackageServers()) {
listSpecs(specList, next);
}
addCIBuildSpecs(specList);
}
public NpmPackage loadPackage(String id, String v) throws FHIRException, IOException {
@Override
public NpmPackage loadPackage(String id, String version) throws FHIRException, IOException {
//ok, try to resolve locally
if (!Utilities.noString(v) && v.startsWith("file:")) {
return loadPackageFromFile(id, v.substring(5));
if (!Utilities.noString(version) && version.startsWith("file:")) {
return loadPackageFromFile(id, version.substring(5));
}
NpmPackage p = loadPackageFromCacheOnly(id, v);
NpmPackage p = loadPackageFromCacheOnly(id, version);
if (p != null) {
if ("current".equals(v)) {
if ("current".equals(version)) {
p = checkCurrency(id, p);
}
if (p != null)
return p;
}
if ("dev".equals(v)) {
if ("dev".equals(version)) {
p = loadPackageFromCacheOnly(id, "current");
p = checkCurrency(id, p);
if (p != null)
return p;
v = "current";
version = "current";
}
// nup, don't have it locally (or it's expired)
InputStreamWithSrc source;
if ("current".equals(v)) {
FilesystemPackageCacheManager.InputStreamWithSrc source;
if ("current".equals(version)) {
// special case - fetch from ci-build server
source = loadFromCIBuild(id);
} else {
source = loadFromPackageServer(id, v);
source = loadFromPackageServer(id, version);
}
return addPackageToCache(id, v == null ? source.version : v, source.stream, source.url);
return addPackageToCache(id, version == null ? source.version : version, source.stream, source.url);
}
// ---------- Current Build SubSystem --------------------------------------------------------------------------------------
private boolean buildLoaded = false;
private Map<String, String> ciList = new HashMap<String, String>();
private JsonArray buildInfo;
private InputStream fetchFromUrlSpecific(String source, boolean optional) throws FHIRException {
try {
URL url = new URL(source);
@ -716,6 +497,41 @@ public class PackageCacheManager {
}
}
private String getPackageUrlFromBuildList(String packageId) throws IOException {
checkBuildLoaded();
for (JsonElement n : buildInfo) {
JsonObject o = (JsonObject) n;
if (packageId.equals(JSONUtil.str(o, "package-id"))) {
return JSONUtil.str(o, "url");
}
}
return null;
}
private void addCIBuildSpecs(Map<String, String> specList) throws IOException {
checkBuildLoaded();
for (JsonElement n : buildInfo) {
JsonObject o = (JsonObject) n;
if (!specList.containsKey(JSONUtil.str(o, "package-id"))) {
specList.put(JSONUtil.str(o, "package-id"), JSONUtil.str(o, "url"));
}
}
}
@Override
public String getPackageId(String canonicalUrl) throws IOException {
String retVal = super.getPackageId(canonicalUrl);
if (retVal == null) {
retVal = getPackageIdFromBuildList(canonicalUrl);
}
return retVal;
}
// ========================= Package Mgmt API =======================================================================
private String getPackageIdFromBuildList(String canonical) throws IOException {
checkBuildLoaded();
if (buildInfo != null) {
@ -735,29 +551,6 @@ public class PackageCacheManager {
return null;
}
private String getPackageUrlFromBuildList(String packageId) throws IOException {
checkBuildLoaded();
for (JsonElement n : buildInfo) {
JsonObject o = (JsonObject) n;
if (packageId.equals(JSONUtil.str(o, "package-id"))) {
return JSONUtil.str(o, "url");
}
}
return null;
}
private void addCIBuildSpecs(Map<String, String> specList) throws IOException {
checkBuildLoaded();
for (JsonElement n : buildInfo) {
JsonObject o = (JsonObject) n;
if (!specList.containsKey(JSONUtil.str(o, "package-id"))) {
specList.put(JSONUtil.str(o, "package-id"), JSONUtil.str(o, "url"));
}
}
}
private NpmPackage checkCurrency(String id, NpmPackage p) throws IOException {
checkBuildLoaded();
// special case: current versions roll over, and we have to check their currency
@ -785,7 +578,6 @@ public class PackageCacheManager {
return false;
}
private void loadFromBuildServer() throws IOException {
URL url = new URL("https://build.fhir.org/ig/qas.json?nocache=" + System.currentTimeMillis());
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
@ -883,6 +675,9 @@ public class PackageCacheManager {
return null;
}
// ---------- Current Build SubSystem --------------------------------------------------------------------------------------
private String fetchVersionTheOldWay(String id) throws IOException {
String url = getUrlForPackage(id);
if (url == null) {
@ -926,6 +721,135 @@ public class PackageCacheManager {
return res;
}
/**
* if you don't provide and implementation of this interface, the PackageCacheManager will use the web directly.
* <p>
* You can use this interface to
*
* @author graha
*/
public interface INetworkServices {
InputStream resolvePackage(String packageId, String version);
}
public interface CacheLockFunction<T> {
T get() throws IOException;
}
public class BuildRecordSorter implements Comparator<BuildRecord> {
@Override
public int compare(BuildRecord arg0, BuildRecord arg1) {
return arg1.date.compareTo(arg0.date);
}
}
public class BuildRecord {
private String url;
private String packageId;
private String repo;
private Date date;
public BuildRecord(String url, String packageId, String repo, Date date) {
super();
this.url = url;
this.packageId = packageId;
this.repo = repo;
this.date = date;
}
public String getUrl() {
return url;
}
public String getPackageId() {
return packageId;
}
public String getRepo() {
return repo;
}
public Date getDate() {
return date;
}
}
public class VersionHistory {
private String id;
private String canonical;
private String current;
private Map<String, String> versions = new HashMap<>();
public String getCanonical() {
return canonical;
}
public String getCurrent() {
return current;
}
public Map<String, String> getVersions() {
return versions;
}
public String getId() {
return id;
}
}
public class PackageEntry {
private byte[] bytes;
private String name;
public PackageEntry(String name) {
this.name = name;
}
public PackageEntry(String name, byte[] bytes) {
this.name = name;
this.bytes = bytes;
}
}
public class CacheLock {
private final File lockFile;
public CacheLock(String name) throws IOException {
this.lockFile = new File(cacheFolder, name + ".lock");
if (!lockFile.isFile()) {
TextFile.stringToFile("", lockFile);
}
}
public <T> T doWithLock(CacheLockFunction<T> f) throws FileNotFoundException, IOException {
try (FileChannel channel = new RandomAccessFile(lockFile, "rw").getChannel()) {
final FileLock fileLock = channel.lock();
T result = null;
try {
result = f.get();
} finally {
fileLock.release();
}
if (!lockFile.delete()) {
lockFile.deleteOnExit();
}
return result;
}
}
}
//public List<String> getUrls() throws IOException {

View File

@ -0,0 +1,17 @@
package org.hl7.fhir.utilities.cache;
import org.hl7.fhir.exceptions.FHIRException;
import java.io.IOException;
import java.io.InputStream;
public interface IPackageCacheManager {
String getPackageId(String canonicalUrl) throws IOException;
NpmPackage addPackageToCache(String id, String version, InputStream packageTgzInputStream, String sourceDesc) throws IOException;
String getPackageUrl(String packageId) throws IOException;
NpmPackage loadPackage(String id, String version) throws FHIRException, IOException;
}

View File

@ -35,12 +35,12 @@ import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@ -57,20 +57,14 @@ import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.IniFile;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.cache.NpmPackage.IndexVersionSorter;
import org.hl7.fhir.utilities.cache.PackageCacheManager.PackageEntry;
import org.hl7.fhir.utilities.cache.PackageGenerator.PackageType;
import org.hl7.fhir.utilities.json.JSONUtil;
import org.hl7.fhir.utilities.json.JsonTrackingParser;
import com.google.common.base.Charsets;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
@ -109,7 +103,7 @@ public class NpmPackage {
public class NpmPackageFolder {
private String name;
private Map<String, List<String>> types = new HashMap<>();
private Map<String, byte[]> content = new HashMap<String, byte[]>();
private Map<String, byte[]> content = new HashMap<>();
private JsonObject index;
private File folder;
@ -118,6 +112,10 @@ public class NpmPackage {
this.name = name;
}
public Map<String, List<String>> getTypes() {
return types;
}
public String getName() {
return name;
}
@ -198,17 +196,18 @@ public class NpmPackage {
private JsonObject npm;
private Map<String, NpmPackageFolder> folders = new HashMap<>();
private boolean changedByLoader; // internal qa only!
private Map<String, Object> userData = new HashMap<>();
/**
* Constructor
*/
private NpmPackage() {
super();
}
// public NpmPackage(JsonObject npm, Map<String, byte[]> content, List<String> folders) {
// this.path = null;
// this.content = content;
// this.npm = npm;
// this.folders = folders;
// }
/**
* Factory method that parses a package from an extracted folder
*/
public static NpmPackage fromFolder(String path) throws IOException {
NpmPackage res = new NpmPackage();
loadFiles(res, path, new File(path));
@ -216,6 +215,19 @@ public class NpmPackage {
return res;
}
/**
* Factory method that starts a new empty package using the given PackageGenerator to create the manifest
*/
public static NpmPackage empty(PackageGenerator thePackageGenerator) {
NpmPackage retVal = new NpmPackage();
retVal.npm = thePackageGenerator.getRootJsonObject();
return retVal;
}
public Map<String, Object> getUserData() {
return userData;
}
public static void loadFiles(NpmPackage res, String path, File source, String... exemptions) throws FileNotFoundException, IOException {
res.npm = (JsonObject) new com.google.gson.JsonParser().parse(TextFile.fileToString(Utilities.path(path, "package", "package.json")));
res.path = path;
@ -788,7 +800,7 @@ public class NpmPackage {
TextFile.bytesToFile(b, Utilities.path(dir.getAbsolutePath(), n, s));
}
}
byte[] cnt = indexer.build().getBytes(Charset.forName("UTF-8"));
byte[] cnt = indexer.build().getBytes(StandardCharsets.UTF_8);
TextFile.bytesToFile(cnt, Utilities.path(dir.getAbsolutePath(), n, ".index.json"));
}
byte[] cnt = TextFile.stringToBytes(new GsonBuilder().setPrettyPrinting().create().toJson(npm), false);
@ -826,7 +838,7 @@ public class NpmPackage {
tar.closeArchiveEntry();
}
}
byte[] cnt = indexer.build().getBytes(Charset.forName("UTF-8"));
byte[] cnt = indexer.build().getBytes(StandardCharsets.UTF_8);
TarArchiveEntry entry = new TarArchiveEntry(n+"/.index.json");
entry.setSize(cnt.length);
tar.putArchiveEntry(entry);
@ -849,7 +861,9 @@ public class NpmPackage {
stream.write(b);
}
/**
* Keys are resource type names, values are filenames
*/
public Map<String, List<String>> getTypes() {
return folders.get("package").types;
}
@ -941,6 +955,9 @@ public class NpmPackage {
}
public void addFile(String folderName, String name, byte[] cnt, String type) {
if (!folders.containsKey(folderName)) {
folders.put(folderName, new NpmPackageFolder(folderName));
}
NpmPackageFolder folder = folders.get(folderName);
folder.content.put(name, cnt);
if (!folder.types.containsKey(type))

View File

@ -1,5 +1,14 @@
package org.hl7.fhir.utilities.cache;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.json.JSONUtil;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@ -13,18 +22,6 @@ import java.util.Date;
import java.util.List;
import java.util.Set;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.cache.PackageClient.PackageInfo;
import org.hl7.fhir.utilities.json.JSONUtil;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
public class PackageClient {
public class PackageInfo {
@ -109,15 +106,10 @@ public class PackageClient {
}
public InputStream fetchCached(String url) throws IOException, FileNotFoundException {
File cacheFile = new File(Utilities.path(cacheFolder, fn(url)));
if (cacheFile.exists()) {
return new FileInputStream(cacheFile);
}
TextFile.bytesToFile(TextFile.streamToBytes(fetchUrl(url, null)), cacheFile);
return new FileInputStream(cacheFile);
return fetchUrl(url, null);
}
private String fn(String url) {
protected String fn(String url) {
String[] p = url.split("\\/");
return p[2]+"-"+p[p.length-2]+"-"+p[p.length-1]+".tgz";
}

View File

@ -63,9 +63,14 @@ public class PackageGenerator {
throw new Error("Unknown Type");
}
}
private OutputStream stream;
private JsonObject object;
public PackageGenerator() {
object = new JsonObject();
}
public PackageGenerator(OutputStream stream) {
super();
this.stream = stream;
@ -80,6 +85,10 @@ public class PackageGenerator {
}
public JsonObject getRootJsonObject() {
return object;
}
public void commit() throws IOException {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(object);
@ -91,7 +100,8 @@ public class PackageGenerator {
}
public PackageGenerator name(String value) {
object.addProperty("name", "@fhir/"+value);
// NOTE: I removed a prefix of "@fhir/" here. What was this for? -JA
object.addProperty("name", value);
return this;
}

View File

@ -1,6 +1,6 @@
package org.hl7.fhir.utilities.tests;
import org.hl7.fhir.utilities.cache.PackageClient;
import org.hl7.fhir.utilities.cache.CachingPackageClient;
import org.hl7.fhir.utilities.cache.PackageClient.PackageInfo;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@ -8,11 +8,11 @@ import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.util.List;
public class PackageClientTests {
public class CachingPackageClientTests {
@Test
public void testExists() throws IOException {
PackageClient client = new PackageClient("http://packages.fhir.org");
CachingPackageClient client = new CachingPackageClient("http://packages.fhir.org");
Assertions.assertTrue(client.exists("hl7.fhir.r4.core", "4.0.1"));
Assertions.assertTrue(!client.exists("hl7.fhir.r4.core", "1.0.2"));
Assertions.assertTrue(!client.exists("hl7.fhir.nothing", "1.0.1"));
@ -20,7 +20,7 @@ public class PackageClientTests {
@Test
public void testSearch() throws IOException {
PackageClient client = new PackageClient("http://packages.fhir.org");
CachingPackageClient client = new CachingPackageClient("http://packages.fhir.org");
List<PackageInfo> matches = client.search("core", null, null, false);
for (PackageInfo pi : matches) {
System.out.println(pi.toString());
@ -30,14 +30,14 @@ public class PackageClientTests {
@Test
public void testSearchNoMatches() throws IOException {
PackageClient client = new PackageClient("http://packages.fhir.org");
CachingPackageClient client = new CachingPackageClient("http://packages.fhir.org");
List<PackageInfo> matches = client.search("corezxxx", null, null, false);
Assertions.assertTrue(matches.size() == 0);
}
@Test
public void testVersions() throws IOException {
PackageClient client = new PackageClient("http://packages.fhir.org");
CachingPackageClient client = new CachingPackageClient("http://packages.fhir.org");
List<PackageInfo> matches = client.getVersions("Simplifier.Core.STU3");
for (PackageInfo pi : matches) {
System.out.println(pi.toString());
@ -47,14 +47,14 @@ public class PackageClientTests {
@Test
public void testVersionsNone() throws IOException {
PackageClient client = new PackageClient("http://packages.fhir.org");
CachingPackageClient client = new CachingPackageClient("http://packages.fhir.org");
List<PackageInfo> matches = client.getVersions("Simplifier.Core.STU3X");
Assertions.assertTrue(matches.size() == 0);
}
@Test
public void testExists2() throws IOException {
PackageClient client = new PackageClient("http://packages2.fhir.org/packages");
CachingPackageClient client = new CachingPackageClient("http://packages2.fhir.org/packages");
Assertions.assertTrue(client.exists("hl7.fhir.r4.core", "4.0.1"));
Assertions.assertTrue(!client.exists("hl7.fhir.r4.core", "1.0.2"));
Assertions.assertTrue(!client.exists("hl7.fhir.nothing", "1.0.1"));
@ -62,7 +62,7 @@ public class PackageClientTests {
@Test
public void testSearch2() throws IOException {
PackageClient client = new PackageClient("http://packages2.fhir.org/packages");
CachingPackageClient client = new CachingPackageClient("http://packages2.fhir.org/packages");
List<PackageInfo> matches = client.search("core", null, null, false);
for (PackageInfo pi : matches) {
System.out.println(pi.toString());
@ -72,14 +72,14 @@ public class PackageClientTests {
@Test
public void testSearchNoMatches2() throws IOException {
PackageClient client = new PackageClient("http://packages2.fhir.org/packages");
CachingPackageClient client = new CachingPackageClient("http://packages2.fhir.org/packages");
List<PackageInfo> matches = client.search("corezxxx", null, null, false);
Assertions.assertTrue(matches.size() == 0);
}
@Test
public void testVersions2() throws IOException {
PackageClient client = new PackageClient("http://packages2.fhir.org/packages");
CachingPackageClient client = new CachingPackageClient("http://packages2.fhir.org/packages");
List<PackageInfo> matches = client.getVersions("Simplifier.Core.STU3");
for (PackageInfo pi : matches) {
System.out.println(pi.toString());
@ -89,7 +89,7 @@ public class PackageClientTests {
@Test
public void testVersions2A() throws IOException {
PackageClient client = new PackageClient("http://packages2.fhir.org/packages");
CachingPackageClient client = new CachingPackageClient("http://packages2.fhir.org/packages");
List<PackageInfo> matches = client.getVersions("hl7.fhir.us.core");
for (PackageInfo pi : matches) {
System.out.println(pi.toString());
@ -99,7 +99,7 @@ public class PackageClientTests {
@Test
public void testVersionsNone2() throws IOException {
PackageClient client = new PackageClient("http://packages2.fhir.org/packages");
CachingPackageClient client = new CachingPackageClient("http://packages2.fhir.org/packages");
List<PackageInfo> matches = client.getVersions("Simplifier.Core.STU3X");
Assertions.assertTrue(matches.size() == 0);
}

View File

@ -2,10 +2,9 @@ package org.hl7.fhir.utilities.tests;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.cache.NpmPackage;
import org.hl7.fhir.utilities.cache.PackageCacheManager;
import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
import org.hl7.fhir.utilities.cache.ToolsVersion;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import java.io.File;
@ -16,7 +15,7 @@ public class PackageCacheTests {
@Test
public void testPath() throws IOException {
PackageCacheManager cache = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
FilesystemPackageCacheManager cache = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
cache.clear();
List<String> list = cache.listPackages();
if (!list.isEmpty()) {

View File

@ -4,7 +4,6 @@ import org.apache.commons.io.IOUtils;
import org.hl7.fhir.convertors.*;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.r5.conformance.ProfileUtilities;
import org.hl7.fhir.r5.context.IWorkerContext.IContextResourceLoader;
import org.hl7.fhir.r5.context.IWorkerContext.PackageVersion;
@ -33,7 +32,7 @@ import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.cache.NpmPackage;
import org.hl7.fhir.utilities.cache.PackageCacheManager;
import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
import org.hl7.fhir.utilities.cache.ToolsVersion;
import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
@ -42,11 +41,8 @@ import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
import org.hl7.fhir.utilities.xhtml.XhtmlComposer;
import org.xml.sax.SAXException;
import com.google.gson.JsonObject;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
@ -254,7 +250,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
private boolean anyExtensionsAllowed = false;
private String version;
private String language;
private PackageCacheManager pcm;
private FilesystemPackageCacheManager pcm;
private PrintWriter mapLog;
private boolean debug;
private Set<String> loadedIgs = new HashSet<>();
@ -301,7 +297,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
}
public ValidationEngine() throws IOException {
pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
}
public void setTerminologyServer(String src, String log, FhirPublication version) throws Exception {
@ -325,7 +321,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
}
public ValidationEngine(String src, String txsrvr, String txLog, FhirPublication version, boolean canRunWithoutTerminologyServer, String vString) throws Exception {
pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
loadCoreDefinitions(src, false);
context.setCanRunWithoutTerminology(canRunWithoutTerminologyServer);
setTerminologyServer(txsrvr, txLog, version);
@ -333,7 +329,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
}
public ValidationEngine(String src, String txsrvr, String txLog, FhirPublication version, String vString) throws Exception {
pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
loadCoreDefinitions(src, false);
setTerminologyServer(txsrvr, txLog, version);
this.version = vString;
@ -341,7 +337,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
public ValidationEngine(String src) throws Exception {
loadCoreDefinitions(src, false);
pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
}
public String getLanguage() {
@ -473,7 +469,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
res.put(Utilities.changeFileExt(src, "."+fmt.getExtension()), TextFile.fileToBytesNCS(src));
return res;
}
} else if ((src.matches(PackageCacheManager.PACKAGE_REGEX) || src.matches(PackageCacheManager.PACKAGE_VERSION_REGEX)) && !src.endsWith(".zip") && !src.endsWith(".tgz")) {
} else if ((src.matches(FilesystemPackageCacheManager.PACKAGE_REGEX) || src.matches(FilesystemPackageCacheManager.PACKAGE_VERSION_REGEX)) && !src.endsWith(".zip") && !src.endsWith(".tgz")) {
return fetchByPackage(src);
}
throw new Exception("Unable to find/resolve/read -ig "+src);
@ -627,7 +623,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
}
if (pcm == null) {
log("Creating Package manager?");
pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
}
if (version == null) {
version = pcm.getLatestVersion(id);

View File

@ -2,7 +2,7 @@ package org.hl7.fhir.validation.cli.utils;
import org.hl7.fhir.r5.model.Constants;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.cache.PackageCacheManager;
import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
import org.hl7.fhir.utilities.cache.ToolsVersion;
import java.io.IOException;
@ -20,7 +20,7 @@ public class Display {
System.out.print(s.contains(" ") ? " \"" + s + "\"" : " " + s);
}
System.out.println();
System.out.println("Directories: Current = " + System.getProperty("user.dir") + ", Package Cache = " + new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION).getFolder());
System.out.println("Directories: Current = " + System.getProperty("user.dir") + ", Package Cache = " + new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION).getFolder());
}
public static void displayHelpDetails() {

View File

@ -6,14 +6,11 @@ import java.util.List;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.context.SimpleWorkerContext;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.cache.NpmPackage;
import org.hl7.fhir.utilities.cache.PackageCacheManager;
import org.hl7.fhir.utilities.cache.PackageClient;
import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
import org.hl7.fhir.utilities.cache.CachingPackageClient;
import org.hl7.fhir.utilities.cache.PackageClient.PackageInfo;
import org.xml.sax.InputSource;
import org.hl7.fhir.utilities.cache.ToolsVersion;
public class PackageValidator {
@ -23,9 +20,9 @@ public class PackageValidator {
}
private void execute() throws IOException {
PackageCacheManager pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
FilesystemPackageCacheManager pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
PackageClient pc = new PackageClient(PackageCacheManager.PRIMARY_SERVER);
CachingPackageClient pc = new CachingPackageClient(FilesystemPackageCacheManager.PRIMARY_SERVER);
for (PackageInfo t : pc.search(null, null, null, false)) {
System.out.println("Check Package "+t.getId());
List<PackageInfo> vl = pc.getVersions(t.getId());

View File

@ -30,7 +30,7 @@ import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.cache.NpmPackage;
import org.hl7.fhir.utilities.cache.PackageCacheManager;
import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
import org.hl7.fhir.utilities.cache.ToolsVersion;
import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
@ -102,7 +102,7 @@ public class ComparisonTests {
if (!new File(Utilities.path("[tmp]", "comparison")).exists()) {
System.out.println("---- Set up Output ----------------------------------------------------------");
Utilities.createDirectory(Utilities.path("[tmp]", "comparison"));
PackageCacheManager pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
FilesystemPackageCacheManager pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
NpmPackage npm = pcm.loadPackage("hl7.fhir.pubpack", "0.0.5");
for (String f : npm.list("other")) {
TextFile.streamToFile(npm.load("other", f), Utilities.path("[tmp]", "comparison", f));

View File

@ -21,7 +21,7 @@ import org.hl7.fhir.r4.utils.StructureMapUtilities.ITransformerServices;
import org.hl7.fhir.utilities.IniFile;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.cache.PackageCacheManager;
import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
import org.hl7.fhir.utilities.cache.ToolsVersion;
import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
@ -42,7 +42,7 @@ import java.util.zip.ZipInputStream;
public class R3R4ConversionTests implements ITransformerServices, IValidatorResourceFetcher {
private static final boolean SAVING = true;
private PackageCacheManager pcm = null;
private FilesystemPackageCacheManager pcm = null;
public static Stream<Arguments> data() throws ParserConfigurationException, SAXException, IOException {
if (!(new File(Utilities.path(TestingUtilities.home(), "implementations", "r3maps", "outcomes.json")).exists()))
@ -285,7 +285,7 @@ public class R3R4ConversionTests implements ITransformerServices, IValidatorReso
if (contextR3 != null)
return;
pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
R3ToR4Loader ldr = new R3ToR4Loader().setPatchUrls(true).setKillPrimitives(true);
System.out.println("loading R3");

View File

@ -58,7 +58,7 @@ import org.hl7.fhir.utilities.CSFile;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.cache.PackageCacheManager;
import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
import org.hl7.fhir.utilities.cache.ToolsVersion;
import org.w3c.dom.Document;
@ -83,9 +83,9 @@ public class TestingUtilitiesX {
fcontexts = new HashMap<>();
}
if (!fcontexts.containsKey(version)) {
PackageCacheManager pcm;
FilesystemPackageCacheManager pcm;
try {
pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
IWorkerContext fcontext = SimpleWorkerContext.fromPackage(pcm.loadPackage(VersionUtilities.packageForVersion(version), version), loaderForVersion(version));
fcontext.setUcumService(new UcumEssenceService(TestingUtilitiesX.loadTestResourceStream("ucum", "ucum-essence.xml")));
fcontext.setExpansionProfile(new Parameters());

View File

@ -1,18 +1,5 @@
package org.hl7.fhir.validation.tests;
import java.io.File;
import java.util.UUID;
import org.hl7.fhir.convertors.R5ToR5Loader;
import org.hl7.fhir.r5.conformance.ProfileComparer;
import org.hl7.fhir.r5.model.FhirPublication;
import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.utils.KeyGenerator;
import org.hl7.fhir.utilities.cache.PackageCacheManager;
import org.hl7.fhir.utilities.cache.ToolsVersion;
import org.hl7.fhir.r5.test.utils.TestingUtilities;
import org.hl7.fhir.validation.ValidationEngine;
import org.hl7.fhir.validation.tests.utilities.TestUtilities;
import org.junit.jupiter.api.Test;
public class ProfileComparisonTests {

View File

@ -147,7 +147,9 @@
<target>1.8</target>
<forceJavacCompilerUse>false</forceJavacCompilerUse>
<encoding>UTF-8</encoding>
<fork>false</fork>
<!-- Allows running the compiler in a separate process. If false it uses the built in compiler,
while if true it will use an executable. -->
<fork>true</fork>
<meminitial>512m</meminitial>
<maxmem>4000m</maxmem>
<debug>true</debug>
@ -159,6 +161,9 @@
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven_surefire_version}</version>
<configuration>
<forkCount>1</forkCount>
<reuseForks>true</reuseForks>
<parallel>classes</parallel>
<trimStackTrace>false</trimStackTrace>
<testFailureIgnore>false</testFailureIgnore>
<!-- We need to include the ${argLine} here so the Jacoco test arguments are included in the