package org.apache.sling.installer.factory.model.impl;/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.io.StringWriter; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.apache.sling.installer.api.InstallableResource; import org.apache.sling.installer.api.tasks.RegisteredResource; import org.apache.sling.installer.api.tasks.ResourceTransformer; import org.apache.sling.installer.api.tasks.TransformationResult; import org.apache.sling.provisioning.model.Artifact; import org.apache.sling.provisioning.model.Feature; import org.apache.sling.provisioning.model.Model; import org.apache.sling.provisioning.model.ModelUtility; import org.apache.sling.provisioning.model.Traceable; import org.apache.sling.provisioning.model.io.ModelArchiveReader; import org.apache.sling.provisioning.model.io.ModelReader; import org.apache.sling.provisioning.model.io.ModelWriter; import org.osgi.framework.BundleContext; import org.osgi.framework.Version; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This transformer detects a file with the ending ".model" containing * a provisioning model or a model archive ending in ".mar" */ @Component(service = ResourceTransformer.class) public class ModelTransformer implements ResourceTransformer { public static final String TYPE_PROV_MODEL = "provisioningmodel"; public static final String ATTR_MODEL = "model"; public static final String ATTR_FEATURE_INDEX = "feature"; public static final String ATTR_BASE_PATH = "path"; public static final String ATTR_FEATURE_NAME = "name"; /** Logger. */ private final Logger logger = LoggerFactory.getLogger(this.getClass()); private BundleContext bundleContext; @Activate private void activate(final BundleContext bc) { this.bundleContext = bc; } @Override public TransformationResult[] transform(final RegisteredResource resource) { Model model = null; File baseDir = null; if ( resource.getType().equals(InstallableResource.TYPE_FILE) && resource.getURL().endsWith(".model") ) { try ( final Reader reader = new InputStreamReader(resource.getInputStream(), "UTF-8") ) { model = ModelReader.read(reader, resource.getURL()); } catch ( final IOException ioe) { logger.info("Unable to read model from " + resource.getURL(), ioe); } } if ( resource.getType().equals(InstallableResource.TYPE_FILE) && resource.getURL().endsWith(".mar") ) { baseDir = this.bundleContext.getDataFile(""); try ( final InputStream is = resource.getInputStream() ) { model = ModelArchiveReader.read(is, new ModelArchiveReader.ArtifactConsumer() { @Override public void consume(final Artifact artifact, final InputStream is) throws IOException { // nothing to do, install task does extraction } }); } catch ( final IOException ioe) { logger.info("Unable to read model from " + resource.getURL(), ioe); } } if ( model != null ) { Map<Traceable, String> errors = ModelUtility.validate(model); if ( errors == null ) { try { final Model effectiveModel = ModelUtility.getEffectiveModel(model); errors = ModelUtility.validateIncludingVersion(effectiveModel); if ( errors == null ) { String modelTxt = null; try ( final StringWriter sw = new StringWriter()) { ModelWriter.write(sw, effectiveModel); modelTxt = sw.toString(); } catch ( final IOException ioe) { logger.info("Unable to read model from " + resource.getURL(), ioe); } if ( modelTxt != null ) { final TransformationResult[] result = new TransformationResult[effectiveModel.getFeatures().size()]; int index = 0; for(final Feature f : effectiveModel.getFeatures()) { final TransformationResult tr = new TransformationResult(); tr.setResourceType(TYPE_PROV_MODEL); tr.setId(f.getName()); tr.setVersion(new Version(f.getVersion())); final Map<String, Object> attributes = new HashMap<>(); attributes.put(ATTR_MODEL, modelTxt); attributes.put(ATTR_FEATURE_INDEX, index); attributes.put(ATTR_FEATURE_NAME, f.getName() + "-" + f.getVersion()); if ( baseDir != null ) { final File dir = new File(baseDir, f.getName() + "-" + f.getVersion()); attributes.put(ATTR_BASE_PATH, dir.getAbsolutePath()); } tr.setAttributes(attributes); result[index] = tr; index++; } return result; } } } catch ( final IllegalArgumentException iae ) { errors = Collections.singletonMap((Traceable)model, iae.getMessage()); } } if ( errors != null ) { logger.warn("Errors during parsing model at {} : {}", resource.getURL(), errors.values()); } } return null; } }