All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.atlasmap.core.ADMArchiveHandler Maven / Gradle / Ivy

/**
 * Copyright (C) 2017 Red Hat, 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 io.atlasmap.core;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Path;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.GZIPInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

import org.slf4j.LoggerFactory;

import org.slf4j.Logger;

import io.atlasmap.api.AtlasException;
import io.atlasmap.v2.ADMDigest;
import io.atlasmap.v2.AtlasMapping;
import io.atlasmap.v2.DataSourceKey;
import io.atlasmap.v2.DataSourceMetadata;
import io.atlasmap.v2.Json;

/**
 * 
* The API for handling ADM archive. It encapsulates ADM archive structure * and format and isolate file/stream I/O from other part. * ADM archive is a zipped archive file or its exploded directory which contains *
    *
  • Mapping Definition file (atlasmapping-UI.n.json)
  • *
  • Gzipped digest file which contains all non-Java document metadata * and mapping definition in a single JSON file (adm-catalog-files-n.gz)
  • *
  • Java libraries (jar files in lib/ directory)
  • *
*
* {@link #load(Path)} {@link #export(OutputStream)} * *
* This handler follows lazy loading strategy as much as * possible, i.e. defer to serialize/deserialize until it is really required. * Also note that at this moment Java library directory is not managed by this class. * Only when it imports/exports ADM archive file, library jars are extracted/bundled * if {@link #isIgnoreLibrary} is set to {@code false}. *
* *
* TODO * https://github.com/atlasmap/atlasmap/issues/1476 * A gzipped digest file have to be splitted into individual schemas and a catalog file. *
*/ public class ADMArchiveHandler { private static final Logger LOG = LoggerFactory.getLogger(ADMArchiveHandler.class); private static final String MAPPING_DEFINITION_FILTER = "atlasmapping"; private static final String MAPPING_DEFINITION_TEMPLATE = "atlasmapping-UI.%s.json"; private static final String GZIPPED_ADM_DIGEST_FILTER = "adm-catalog-files"; private static final String GZIPPED_ADM_DIGEST_TEMPLATE = "adm-catalog-files-%s.gz"; private byte[] buffer = new byte[2048]; private byte[] gzippedAdmDigestBytes = null; private byte[] mappingDefinitionBytes = null; private ObjectMapper jsonMapper; private ObjectMapper jsonMapperForDigest; private AtlasMapping mappingDefinition = null; private String mappingDefinitionId = "0"; private Map dataSourceMetadata; private boolean ignoreLibrary = false; private Path persistDirectory; private Path libraryDirectory; public ADMArchiveHandler() { this(ADMArchiveHandler.class.getClassLoader()); } public ADMArchiveHandler(ClassLoader loader) { this.jsonMapper = Json.withClassLoader(loader); this.jsonMapperForDigest = this.jsonMapper.copy(); this.jsonMapperForDigest.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, false); } /** * Load an ADM archive file or an exploded directory. * @param path {@code java.nio.file.Path} of the ADM archive file or an exploded directory * @throws AtlasException If it fails to load */ public void load(Path path) throws AtlasException { clear(); File file = path.toFile(); if (!file.exists() || (!file.isFile() && !file.isDirectory())) { throw new AtlasException( String.format("'%s' doesn't exist or is not a regular file/directory", path.toString())); } if (file.isDirectory()) { loadExploded(file); } else { loadADMFile(file); } } /** * Load an ADM archive from stream. * @param in InputStream to read an ADM Archive * @throws AtlasException If it fails to load */ public void load(InputStream in) throws AtlasException { loadADMStream(in); } /** * Export into an ADM archive. * @param out OutputStream to write an ADM archive * @throws AtlasException If it fails to export */ public void export(OutputStream out) throws AtlasException { LOG.debug("Creating ADM archive file for ID:'{}'", this.mappingDefinitionId); try (ZipOutputStream zipOut = new ZipOutputStream(out)) { ZipEntry catEntry = null; if (this.getMappingDefinitionBytes() != null) { String mappingFileName = getMappingDefinitionFileName(); LOG.debug(" Creating mapping definition file '{}'", mappingFileName); catEntry = new ZipEntry(mappingFileName); zipOut.putNextEntry(catEntry); zipOut.write(getMappingDefinitionBytes(), 0, getMappingDefinitionBytes().length); zipOut.closeEntry(); } if (getGzippedADMDigestBytes() != null) { LOG.debug(" Creating gzipped ADM digest file '{}'", getGzippedADMDigestFileName()); catEntry = new ZipEntry(getGzippedADMDigestFileName()); zipOut.putNextEntry(catEntry); zipOut.write(getGzippedADMDigestBytes(), 0, getGzippedADMDigestBytes().length); zipOut.closeEntry(); zipOut.putNextEntry(new ZipEntry("lib/")); zipOut.closeEntry(); } if (!isIgnoreLibrary() && libraryDirectory != null && libraryDirectory.toFile().isDirectory()) { for (File jarFile : libraryDirectory.toFile().listFiles()) { LOG.debug(" Creating jar file entry '{}'", "lib/" + jarFile.getName()); ZipEntry libEntry = new ZipEntry("lib/" + jarFile.getName()); zipOut.putNextEntry(libEntry); redirectStream(new FileInputStream(jarFile), zipOut); zipOut.closeEntry(); } } } catch (Exception e) { throw new AtlasException("Error exporting ADM archive file", e); } } /** * Persist ADM archive into a directory. * @throws AtlasException If it fails to persist */ public void persist() throws AtlasException { if (this.persistDirectory == null) { throw new AtlasException("Persist Directory must be set"); } Path mdPath = this.persistDirectory.resolve(getMappingDefinitionFileName()); if (getMappingDefinitionBytes() != null) { try { jsonMapper.readValue(getMappingDefinitionBytes(), AtlasMapping.class); } catch (Exception e) { LOG.warn("Invalid serialized mapping definition content detected, discarding"); this.mappingDefinitionBytes = null; } } if (getMappingDefinitionBytes() != null) { try (FileOutputStream out = new FileOutputStream(mdPath.toFile())) { out.write(getMappingDefinitionBytes()); } catch (Exception e) { LOG.warn("Failed to persist mapping definition", e); } } if (getGzippedADMDigestBytes() != null) { Path digestPath = this.persistDirectory.resolve(getGzippedADMDigestFileName()); try (FileOutputStream out = new FileOutputStream(digestPath.toFile())) { out.write(getGzippedADMDigestBytes()); } catch (Exception e) { LOG.warn("Failed to persist gzipped ADM digest file"); } } } public AtlasMapping getMappingDefinition() { if (this.mappingDefinition == null && this.mappingDefinitionBytes != null) { try { this.mappingDefinition = jsonMapper.readValue(this.mappingDefinitionBytes, AtlasMapping.class); } catch (Exception e) { LOG.warn("Invalid serialized mapping definition content detected, discarding"); this.mappingDefinitionBytes = null; } } return this.mappingDefinition; } public void setMappingDefinition(AtlasMapping mapping) { this.mappingDefinitionBytes = null; this.mappingDefinition = mapping; } public void setMappingDefinitionBytes(InputStream is) throws AtlasException { try { this.mappingDefinition = null; this.mappingDefinitionBytes = readIntoByteArray(is); if (LOG.isDebugEnabled()) { LOG.debug(this.jsonMapper.writeValueAsString(getMappingDefinition())); } } catch (Exception e) { throw new AtlasException(e); } } public byte[] getMappingDefinitionBytes() throws AtlasException { try { if (this.mappingDefinitionBytes == null && this.mappingDefinition != null) { this.mappingDefinitionBytes = jsonMapper.writeValueAsBytes(this.mappingDefinition); } return this.mappingDefinitionBytes; } catch (Exception e) { throw new AtlasException(e); } } public void setGzippedADMDigest(InputStream is) throws AtlasException { try { this.gzippedAdmDigestBytes = readIntoByteArray(is); } catch (Exception e) { throw new AtlasException(e); } } public byte[] getGzippedADMDigestBytes() { return this.gzippedAdmDigestBytes; } public DataSourceMetadata getDataSourceMetadata(boolean isSource, String documentId) throws AtlasException { return getDataSourceMetadata(new DataSourceKey(isSource, documentId)); } public DataSourceMetadata getDataSourceMetadata(DataSourceKey key) throws AtlasException { if (getDataSourceMetadataMap() == null) { return null; } return getDataSourceMetadataMap().get(key); } public Map getDataSourceMetadataMap() throws AtlasException { if (this.dataSourceMetadata == null) { if (this.gzippedAdmDigestBytes == null) { return null; } try (GZIPInputStream in = new GZIPInputStream(new ByteArrayInputStream(this.gzippedAdmDigestBytes))) { ADMDigest digest = jsonMapperForDigest.readValue(in, ADMDigest.class); this.dataSourceMetadata = new HashMap<>(); for (int i=0; i 0) { out.write(buffer, 0, len); } } private byte[] readIntoByteArray(InputStream in) throws Exception { try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { redirectStream(in, baos); return baos.toByteArray(); } } private boolean ensureDirectory(Path dir) throws AtlasException { if (dir == null) { throw new AtlasException(String.format("Directory must not be Null")); } File dirf = dir.toFile(); if (!dirf.isDirectory()) { throw new AtlasException(String.format("File '%s' is not a directory", dirf.getAbsolutePath())); } if (!dirf.exists()) { dirf.mkdirs(); } return true; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy