org.overlord.sramp.server.mvn.services.MavenMetaDataBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.overlord.sramp.server.mvn.services.MavenMetaDataBuilder.java

Source

/*
 * Copyright 2014 JBoss 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 org.overlord.sramp.server.mvn.services;

import java.text.ParseException;
import java.text.SimpleDateFormat;

import org.apache.commons.lang.StringUtils;
import org.overlord.sramp.repository.QueryManager;
import org.overlord.sramp.repository.QueryManagerFactory;
import org.overlord.sramp.repository.query.SrampQuery;
import org.overlord.sramp.server.i18n.Messages;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Builder class that construct a MavenMetadata object based on an url String
 * which correct format would be groupId/groupId.../version/file_name In case
 * that the url can not be converted to a correct maven metadata object, it
 * would return a MavenMetadata with all its attributes with an empty value.
 *
 * @author David Virgil Naranjo
 */
public class MavenMetaDataBuilder {

    private static Logger logger = LoggerFactory.getLogger(MavenMetaDataBuilder.class);

    /**
     * Builds the Maven Metadata based on a URL, which format is supposed to be /groupId.../artifactId/versionId/filename
     *
     * @param url
     *            the url
     * @return the maven meta data
     */
    public static MavenMetaData build(String url) {
        String groupId = ""; //$NON-NLS-1$
        String artifactId = ""; //$NON-NLS-1$
        String version = ""; //$NON-NLS-1$
        String type = ""; //$NON-NLS-1$
        String classifier = ""; //$NON-NLS-1$
        String parentType = ""; //$NON-NLS-1$
        String fileName = ""; //$NON-NLS-1$
        String snapshotId = ""; //$NON-NLS-1$

        if (url.startsWith("/")) { //$NON-NLS-1$
            url = url.substring(1);
        }

        int lastPathSegmentIdx = url.lastIndexOf('/');
        String lastPathSegment = null;
        if (lastPathSegmentIdx != -1) {
            lastPathSegment = url.substring(lastPathSegmentIdx + 1);
        }
        //This means the last part contains a file with a file extension
        if (lastPathSegment != null && lastPathSegment.indexOf('.') != -1) {
            String[] tokens = url.split("/"); //$NON-NLS-1$
            if (tokens != null && tokens.length > 0) {
                //There could be files either in the artifact folder(maven-metadata.xml) or in the version folder.
                //Then for that it is mandatory to have more than 2 tokens. At least one for groupId, one for artifactId and one for fileName
                if (tokens.length >= 3) {

                    if (lastPathSegment.contains("maven-metadata.xml")) { //$NON-NLS-1$
                        String possibleGroupId = ""; //$NON-NLS-1$

                        boolean isGroup = false;
                        // There are checked the different possibilities about
                        // groupsIds.
                        // It is checked in s-ramp

                        // It is checked from the end to the beginning to avoid
                        // the case that an artifact is contained in a groupId
                        // that contains subgroups
                        // First store the biggest possibility, not until the
                        // last token. The last would be the filename and the
                        // previous could be the artifactId
                        for (int i = 0; i < tokens.length - 2; i++) {
                            possibleGroupId += tokens[i];
                            if (i < tokens.length - 1) {
                                possibleGroupId += "."; //$NON-NLS-1$
                            }

                        }
                        // For example for org.overlord.test the number of
                        // checks is going to be 3
                        int iterations = StringUtils.countMatches(possibleGroupId, ".") + 1; //$NON-NLS-1$
                        for (int i = 0; i < iterations; i++) {
                            if (isGroupId(possibleGroupId)) {
                                isGroup = true;
                                break;
                            }
                            if (possibleGroupId.lastIndexOf(".") != -1) { //$NON-NLS-1$
                                possibleGroupId = possibleGroupId.substring(0, possibleGroupId.lastIndexOf(".")); //$NON-NLS-1$
                            }
                        }
                        // If there is a group in s-ramp that matches the
                        // request
                        if (isGroup) {
                            // This means there is an existing groupId in s-ramp
                            groupId = possibleGroupId;
                            String lastGroupIdToken = ""; //$NON-NLS-1$
                            if (groupId.contains(".")) { //$NON-NLS-1$
                                lastGroupIdToken = groupId.substring(groupId.lastIndexOf(".") + 1); //$NON-NLS-1$
                            } else {
                                lastGroupIdToken = groupId;
                            }
                            int groupIdIndex = 0;
                            for (groupIdIndex = 0; groupIdIndex < tokens.length; groupIdIndex++) {
                                if (tokens[groupIdIndex].equals(lastGroupIdToken)) {
                                    break;
                                }
                            }

                            if (tokens.length == (groupIdIndex + 3)) {
                                // This means it comes a file under the artifact
                                // id.
                                // Example:
                                // /org/test/artifact/maven-metadata.xml
                                // where org/test is the groupId
                                artifactId = tokens[groupIdIndex + 1];
                                if (!existVersion(groupId, tokens[groupIdIndex + 2])) {
                                    fileName = tokens[groupIdIndex + 2];
                                }
                            } else if (tokens.length == (groupIdIndex + 4)) {
                                // This means it comes a file under the version
                                // id.
                                // Example:
                                // /org/test/artifact/0.0.1/maven-metadata.xml
                                // where
                                // org/test is the groupId abd
                                // artifactId=artifact
                                // and version=0.0.1
                                artifactId = tokens[groupIdIndex + 1];
                                version = tokens[groupIdIndex + 2];
                                fileName = tokens[groupIdIndex + 3];
                            }

                        } else {
                            // If the groupId can not be found in s-ramp then,
                            // it is built a default metadata.
                            // Remember that this method is called, both listing
                            // content and creating new content
                            version = tokens[tokens.length - 2];
                            for (int i = 0; i < tokens.length - 2; i++) {
                                if (i < tokens.length - 3) {
                                    if (i != 0) {
                                        groupId += "."; //$NON-NLS-1$
                                    }
                                    groupId += tokens[i];
                                } else {
                                    artifactId = tokens[i];
                                }
                            }
                            fileName = tokens[tokens.length - 1];

                        }
                    } else {
                        //If the groupId can not be found in s-ramp then, it is built a default metadata.
                        //Remember that this method is called, both listing content and creating new content
                        version = tokens[tokens.length - 2];
                        for (int i = 0; i < tokens.length - 2; i++) {
                            if (i < tokens.length - 3) {
                                if (i != 0) {
                                    groupId += "."; //$NON-NLS-1$
                                }
                                groupId += tokens[i];
                            } else {
                                artifactId = tokens[i];
                            }
                        }
                        fileName = tokens[tokens.length - 1];

                    }

                    //It is parsed the fileName to get information about the classifier
                    if (StringUtils.isNotBlank(fileName)) {
                        type = fileName.substring(fileName.lastIndexOf(".") + 1); //$NON-NLS-1$

                        classifier = ""; //$NON-NLS-1$
                        //We know the information about classifier comes in files that are under the version folder

                        if (StringUtils.isNotBlank(version)) {
                            String versionParsed = ""; //$NON-NLS-1$
                            //When the version contains a -SNAPSHOT, then the filename is artifactId-versionWithoutSNAPSHOT
                            //The snapshot keyword is substitute by a timestamp-counter
                            if (version.contains("-SNAPSHOT")) { //$NON-NLS-1$
                                versionParsed = version.substring(0, version.lastIndexOf("-SNAPSHOT")); //$NON-NLS-1$
                            } else {
                                versionParsed = version;
                            }
                            if (!fileName.contains(version)
                                    && fileName.startsWith(artifactId + "-" + versionParsed)) { //$NON-NLS-1$
                                String without_extension = fileName.substring(0, fileName.lastIndexOf(".")); //$NON-NLS-1$
                                if (StringUtils.countMatches(without_extension, "-") >= 2) { //$NON-NLS-1$
                                    int versionIdx = without_extension.indexOf(versionParsed);
                                    int versionLen = versionParsed.length();
                                    int classifierIdx = versionIdx + versionLen;
                                    if (classifierIdx < without_extension.length()) {
                                        //If it is an snapshop
                                        if (version.contains("SNAPSHOT") && !version.equals(versionParsed)) { //$NON-NLS-1$
                                            String rest = without_extension.substring(classifierIdx + 1);
                                            //All the tokens from the clasifierIdx to the end are splitted by '-'
                                            String[] tokens_file_name = rest.split("-"); //$NON-NLS-1$
                                            if (tokens_file_name.length > 0) {
                                                //It is expected a timestamp
                                                if (isMavenTimeStamp(tokens_file_name[0])) {
                                                    if (tokens_file_name.length > 1) {
                                                        try {
                                                            //The it is expected maybe a counter
                                                            String[] counter = StringUtils
                                                                    .split(tokens_file_name[1], "."); //$NON-NLS-1$
                                                            Integer.parseInt(counter[0]);
                                                            snapshotId = tokens_file_name[0] + "-" + counter[0]; //$NON-NLS-1$
                                                            if (tokens_file_name.length > 2) {
                                                                classifier = tokens_file_name[2];
                                                            } else if (counter.length == 2) {
                                                                parentType = counter[1];
                                                            }
                                                        } catch (NumberFormatException nfe) {
                                                            //In case the parseInt throw an exception it means there is not any counter, and then the classifier goes to the end of the filename
                                                            classifier = rest
                                                                    .substring(tokens_file_name[0].length() + 1);
                                                        }
                                                    }
                                                } else {
                                                    classifier = rest;
                                                }
                                            }
                                        } else {
                                            //This means the version is not snapshot or there is no timestamp in the file
                                            classifier = without_extension.substring(classifierIdx);
                                        }

                                        if (StringUtils.isNotBlank(classifier)) {
                                            if (classifier.contains(".")) {//$NON-NLS-1$
                                                if (classifier.startsWith(".")) { //$NON-NLS-1$
                                                    parentType = classifier.substring(1);
                                                    classifier = ""; //$NON-NLS-1$
                                                } else {
                                                    parentType = classifier
                                                            .substring(classifier.lastIndexOf(".") + 1); //$NON-NLS-1$
                                                    classifier = classifier.substring(0,
                                                            classifier.lastIndexOf(".")); //$NON-NLS-1$
                                                }
                                            }
                                        }
                                    }
                                }
                            }

                        }

                    }

                }
            }
        }
        //If the type, belongs to the MavenFileExtensionEnum, it means than it is sha1 or md5.
        if (MavenFileExtensionEnum.value(type) != null) {
            //Then the parent type has to be filled. We know that the parent type can be taken from the filename
            String without_ext = fileName.substring(0, fileName.lastIndexOf("." + type)); //$NON-NLS-1$
            if (without_ext.contains(".")) { //$NON-NLS-1$
                parentType = without_ext.substring(without_ext.lastIndexOf(".") + 1); //$NON-NLS-1$
            }
        }

        return new MavenMetaData(groupId, artifactId, version, type, classifier, snapshotId, parentType, fileName);

    }

    /**
     * Checks that there are items in s-ramp with an specific group maven id
     *
     * @param groupId
     *            the group id
     * @return true, if is group id
     */
    private static boolean isGroupId(String groupId) {
        String query = "/s-ramp[@maven.groupId = ?]"; //$NON-NLS-1$
        try {
            QueryManager queryManager = QueryManagerFactory.newInstance();
            SrampQuery srampQuery = queryManager.createQuery(query);

            srampQuery.setString(groupId);

            org.overlord.sramp.repository.query.ArtifactSet artifactSet = srampQuery.executeQuery();
            if (artifactSet.size() > 0) {
                return true;
            }
        } catch (Throwable e) {
            logger.error(Messages.i18n.format("maven.resource.query.error", query), e); //$NON-NLS-1$
        }

        return false;
    }

    /**
     * Checks that there are items in s-ramp with an specific group and version
     * maven id
     *
     * @param groupId
     *            the group id
     * @param version
     *            the version
     * @return true, if successful
     */
    private static boolean existVersion(String groupId, String version) {
        String query = "/s-ramp[@maven.groupId = ? and @maven.version = ? ]"; //$NON-NLS-1$
        try {
            QueryManager queryManager = QueryManagerFactory.newInstance();
            SrampQuery srampQuery = queryManager.createQuery(query);

            srampQuery.setString(groupId);
            srampQuery.setString(version);
            org.overlord.sramp.repository.query.ArtifactSet artifactSet = srampQuery.executeQuery();
            if (artifactSet.size() > 0) {
                return true;
            }
        } catch (Throwable e) {
            logger.error(Messages.i18n.format("maven.resource.query.error", query), e); //$NON-NLS-1$
        }

        return false;
    }

    /**
     * Checks if the parameter is a maven time stamp.
     *
     * @param possibleTimestamp
     *            the possible timestamp
     * @return true, if is maven time stamp
     */
    private static boolean isMavenTimeStamp(String possibleTimestamp) {
        // Timestamp included by maven in the snapthots artifacts.
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd.HHmmss"); //$NON-NLS-1$
        try {
            sdf.parse(possibleTimestamp);
        } catch (ParseException e) {
            return false;
        }
        return true;
    }

}