Package org.apache.sling.ide.impl.vlt.serialization

Source Code of org.apache.sling.ide.impl.vlt.serialization.VltSerializationDataBuilder

/*
* 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.
*/
package org.apache.sling.ide.impl.vlt.serialization;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;

import javax.jcr.Credentials;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.ValueFormatException;
import javax.jcr.nodetype.NodeType;

import org.apache.jackrabbit.vault.fs.api.Aggregate;
import org.apache.jackrabbit.vault.fs.api.Aggregator;
import org.apache.jackrabbit.vault.fs.api.RepositoryAddress;
import org.apache.jackrabbit.vault.fs.api.VaultFile;
import org.apache.jackrabbit.vault.fs.api.VaultFileSystem;
import org.apache.jackrabbit.vault.fs.config.ConfigurationException;
import org.apache.jackrabbit.vault.fs.impl.aggregator.FileAggregator;
import org.apache.jackrabbit.vault.fs.impl.aggregator.GenericAggregator;
import org.apache.jackrabbit.vault.fs.impl.io.DocViewSerializer;
import org.apache.jackrabbit.vault.util.Constants;
import org.apache.jackrabbit.vault.util.JcrConstants;
import org.apache.jackrabbit.vault.util.MimeTypes;
import org.apache.jackrabbit.vault.util.PlatformNameFormat;
import org.apache.jackrabbit.vault.util.Text;
import org.apache.sling.ide.impl.vlt.Activator;
import org.apache.sling.ide.impl.vlt.VaultFsLocator;
import org.apache.sling.ide.jcr.RepositoryUtils;
import org.apache.sling.ide.serialization.SerializationData;
import org.apache.sling.ide.serialization.SerializationDataBuilder;
import org.apache.sling.ide.serialization.SerializationException;
import org.apache.sling.ide.serialization.SerializationKind;
import org.apache.sling.ide.serialization.SerializationKindManager;
import org.apache.sling.ide.transport.ResourceProxy;

public class VltSerializationDataBuilder implements SerializationDataBuilder {

    private VaultFsLocator fsLocator;
    private SerializationKindManager skm;
  private org.apache.sling.ide.transport.Repository repo;
  private Session session;
  private VaultFileSystem fs;

    public void init(org.apache.sling.ide.transport.Repository repository, File contentSyncRoot)
            throws SerializationException {

      this.repo = repository;
     
        try {
            this.skm = new SerializationKindManager();
            this.skm.init(repository);
            if (!contentSyncRoot.exists()) {
              throw new IllegalArgumentException("contentSyncRoot does not exist: "+contentSyncRoot);
            }

            Repository jcrRepo = RepositoryUtils.getRepository(repo.getRepositoryInfo());
            Credentials credentials = RepositoryUtils.getCredentials(repo.getRepositoryInfo());
           
            session = jcrRepo.login(credentials);

            RepositoryAddress address = RepositoryUtils.getRepositoryAddress(repo.getRepositoryInfo());

            fs = fsLocator.getFileSystem(address, contentSyncRoot, session);
       
        } catch (org.apache.sling.ide.transport.RepositoryException e) {
            throw new SerializationException(e);
        } catch (RepositoryException e) {
            throw new SerializationException(e);
    } catch (IOException e) {
            throw new SerializationException(e);
    } catch (ConfigurationException e) {
            throw new SerializationException(e);
    }
    }
   
    @Override
    public void destroy() {
        if (session != null) {
            session.logout();
        }
    }

    @Override
    public SerializationData buildSerializationData(File contentSyncRoot, ResourceProxy resource) throws SerializationException {

        try {

            List<Aggregate> chain = findAggregateChain(resource);

            if (chain == null) {
              return null;
            }

            Aggregate aggregate = chain.get(chain.size() - 1);

            String fileOrFolderPathHint = calculateFileOrFolderPathHint(chain);

            String nameHint = PlatformNameFormat.getPlatformName(aggregate.getName());

            SerializationKind serializationKind = getSerializationKind(aggregate);

            if (resource.getPath().equals("/") || serializationKind == SerializationKind.METADATA_PARTIAL
                    || serializationKind == SerializationKind.FILE || serializationKind == SerializationKind.FOLDER) {
                nameHint = Constants.DOT_CONTENT_XML;
            } else if (serializationKind == SerializationKind.METADATA_FULL) {
                nameHint += ".xml";
            }

            Activator.getDefault().getPluginLogger()
                    .trace("Got location {0} for path {1}", fileOrFolderPathHint, resource.getPath());

            if (!needsDir(aggregate)) {
                return SerializationData.empty(fileOrFolderPathHint, serializationKind);
            }

            DocViewSerializer s = new DocViewSerializer(aggregate);
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            s.writeContent(out);
           
            byte[] result = out.toByteArray();

            return new SerializationData(fileOrFolderPathHint, nameHint, result, serializationKind);

        } catch (RepositoryException e) {
            throw new SerializationException(e);
        } catch (IOException e) {
            throw new SerializationException(e);
        }
    }

    private SerializationKind getSerializationKind(Aggregate aggregate) throws RepositoryException {

        NodeType[] mixinNodeTypes = aggregate.getNode().getMixinNodeTypes();
        List<String> mixinNodeTypeNames = new ArrayList<String>(mixinNodeTypes.length);
        for (NodeType nodeType : mixinNodeTypes)
            mixinNodeTypeNames.add(nodeType.getName());

        return skm.getSerializationKind(aggregate.getNode()
                .getPrimaryNodeType()
                .getName(), mixinNodeTypeNames);
    }

    private boolean needsDir(Aggregate aggregate) throws RepositoryException, PathNotFoundException,
            ValueFormatException {

        Aggregator aggregator = fs.getAggregateManager().getAggregator(aggregate.getNode(), null);
        boolean needsDir = true;
        if (aggregator instanceof FileAggregator) {
            needsDir = false;
            // TODO - copy-pasted from FileAggregator, and really does not belong here...
            Node content = aggregate.getNode();
            if (content.isNodeType(JcrConstants.NT_FILE)) {
                content = content.getNode(JcrConstants.JCR_CONTENT);
            }
            String mimeType = null;
            if (content.hasProperty(JcrConstants.JCR_MIMETYPE)) {
                try {
                    mimeType = content.getProperty(JcrConstants.JCR_MIMETYPE).getString();
                } catch (RepositoryException e) {
                    // ignore
                }
            }
            if (mimeType == null) {
                // guess mime type from name
                mimeType = MimeTypes.getMimeType(aggregate.getNode().getName(),
                        MimeTypes.APPLICATION_OCTET_STREAM);
            }

            needsDir = !MimeTypes.matches(aggregate.getNode().getName(), mimeType,
                    MimeTypes.APPLICATION_OCTET_STREAM);

            if (!needsDir) {
                if (content.hasProperty(JcrConstants.JCR_MIXINTYPES)) {
                    for (Value v : content.getProperty(JcrConstants.JCR_MIXINTYPES).getValues()) {
                        if (!v.getString().equals(JcrConstants.MIX_LOCKABLE)) {
                            needsDir = true;
                            break;
                        }
                    }
                }
            }

         // TODO - copy-pasted from GenericAggregator
        } else if (aggregator instanceof GenericAggregator) {
            if (isPlainNtFolder(aggregate)) {
                needsDir = false;
            }
        }
        return needsDir;
    }

    private String calculateFileOrFolderPathHint(List<Aggregate> chain) throws RepositoryException {

        ListIterator<Aggregate> aggs = chain.listIterator();
        StringBuilder out = new StringBuilder();
        while (aggs.hasNext()) {
            Aggregate cur = aggs.next();
            if (aggs.previousIndex() == 0) {
                out.append(PlatformNameFormat.getPlatformPath(cur.getPath()));
            } else {
                out.append("/");
                out.append(PlatformNameFormat.getPlatformPath(cur.getRelPath()));
            }

            if (needsDir(cur)) {
                SerializationKind serializationKind = getSerializationKind(cur);

                if (serializationKind == SerializationKind.FILE) {
                    out.append(".dir");
                }

                if (!aggs.hasNext() && serializationKind == SerializationKind.METADATA_FULL) {
                    out.delete(out.lastIndexOf("/"), out.length());
                }
            }
        }

        return out.toString();
    }

    private boolean isPlainNtFolder(Aggregate agg) throws RepositoryException {

        return agg.getNode().getPrimaryNodeType().getName().equals("nt:folder")
                && agg.getNode().getMixinNodeTypes().length == 0;
    }

    /**
     * Returns the aggregates for a specific resource
     *
     * <p>
     * In the simplest case, a single element is returned in the chain, signalling that the aggregate is a top-level
     * one.
     * </p>
     *
     * <p>
     * For leaf aggregates, the list contains the top-most aggregates first and ends up with the leaf-most ones.
     * </p>
     *
     * @param resource the resource to find the aggregate chain for
     * @return a list of aggregates
     * @throws IOException
     * @throws RepositoryException
     */
    private List<Aggregate> findAggregateChain(ResourceProxy resource) throws IOException, RepositoryException {

        VaultFile vaultFile = fs.getFile(PlatformNameFormat.getPlatformPath(resource.getPath()));

        if (vaultFile == null || vaultFile.getAggregate() == null) {
                // this file might be a leaf aggregate of a vaultfile higher in the resource path ; so look for a
                // parent higher

            String parentPath = Text.getRelativeParent(resource.getPath(), 1);
            while (!parentPath.equals("/")) {
                VaultFile parentFile = fs.getFile(PlatformNameFormat.getPlatformPath(parentPath));

                if (parentFile != null) {
                    Aggregate parentAggregate = parentFile.getAggregate();
                    ArrayList<Aggregate> parents = new ArrayList<Aggregate>();
                    parents.add(parentAggregate);
                    List<Aggregate> chain = lookForAggregateInLeaves(resource, parentAggregate, parents);
                    if (chain != null) {
                        return chain;
                    }
                }

                parentPath = Text.getRelativeParent(parentPath, 1);
            }

            return null;
        }


        return Collections.singletonList(vaultFile.getAggregate());
    }

    /**
     * Recursively looks for an aggregate matching the <tt>resource</tt>'s path starting at the <tt>parentAggregate</tt>
     *
     * <p>
     * The returned chain will contain at least one aggregate, in case the resource is contained in a stand-alone (?)
     * aggregate, or multiple aggregates in case the matching aggregate is a leaf one.
     * </p>
     *
     * @param resource the resource
     * @param parentAggregate the known parent aggregate which potentially matches this resource
     * @param chain the chain used to record all intermediate aggregates
     * @return the final aggregate chain
     *
     * @throws RepositoryException
     */
    private List<Aggregate> lookForAggregateInLeaves(ResourceProxy resource, Aggregate parentAggregate,
            List<Aggregate> chain) throws RepositoryException {

        if (parentAggregate == null) {
            return null;
        }

        List<? extends Aggregate> leaves = parentAggregate.getLeaves();
        if (leaves == null) {
            return null;
        }

        for (Aggregate leaf : leaves) {
            if (leaf.getPath().equals(resource.getPath())) {
                chain.add(leaf);
                return chain;
            } else if (Text.isDescendant(leaf.getPath(), resource.getPath())) {
                chain.add(leaf);
                return lookForAggregateInLeaves(resource, leaf, chain);
            }
        }

        return null;
    }

    public void setLocator(VaultFsLocator locator) {

        this.fsLocator = locator;
    }

}
TOP

Related Classes of org.apache.sling.ide.impl.vlt.serialization.VltSerializationDataBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.