/** * Copyright (C) 2014 SignalFuse, Inc. */ package com.github.dockerjava.core; import java.util.regex.Pattern; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; import com.github.dockerjava.api.model.AuthConfig; import com.github.dockerjava.core.exception.InvalidRepositoryNameException; @SuppressWarnings(value = "checkstyle:equalshashcode") public class NameParser { private NameParser() { } // CHECKSTYLE:OFF private static final int RepositoryNameTotalLengthMax = 255; private static final Pattern RepositoryNameComponentRegexp = Pattern.compile("[a-z0-9]+(?:[._-][a-z0-9]+)*"); private static final Pattern RepositoryNameComponentAnchoredRegexp = Pattern.compile("^" + RepositoryNameComponentRegexp.pattern() + "$"); // CHECKSTYLE:ON // private static final Pattern RepositoryNameRegexp = Pattern.compile("(?:" + // RepositoryNameComponentRegexp.pattern() // + "/)*" + RepositoryNameComponentRegexp.pattern()); public static ReposTag parseRepositoryTag(String name) { int n = name.lastIndexOf(':'); if (n < 0) { return new ReposTag(name, ""); } String tag = name.substring(n + 1); if (!tag.contains("/")) { return new ReposTag(name.substring(0, n), tag); } return new ReposTag(name, ""); } public static class ReposTag { public final String repos; public final String tag; public ReposTag(String repos, String tag) { this.repos = repos; this.tag = tag; } @Override public boolean equals(Object obj) { if (obj instanceof ReposTag) { ReposTag other = (ReposTag) obj; return new EqualsBuilder().append(repos, other.repos).append(tag, other.tag).isEquals(); } else { return false; } } @Override public String toString() { return ToStringBuilder.reflectionToString(this, ToStringStyle.SIMPLE_STYLE); } } /* * see https://github.com/docker/distribution/blob/master/registry/api/v2/names.go */ public static void validateRepoName(String name) { if (name.isEmpty()) { throw new InvalidRepositoryNameException(String.format("Invalid empty repository name \"%s\"", name)); } if (name.length() > RepositoryNameTotalLengthMax) { throw new InvalidRepositoryNameException(String.format("Repository name \"%s\" is longer than " + RepositoryNameTotalLengthMax, name)); } String[] components = name.split("/"); for (String component : components) { if (!RepositoryNameComponentAnchoredRegexp.matcher(component).matches()) { throw new InvalidRepositoryNameException(String.format( "Repository name \"%s\" is invalid. Component: %s", name, component)); } } } public static HostnameReposName resolveRepositoryName(String reposName) { if (reposName.contains("://")) { // It cannot contain a scheme! throw new InvalidRepositoryNameException(); } String[] nameParts = reposName.split("/", 2); if (nameParts.length == 1 || (!nameParts[0].contains(".") && !nameParts[0].contains(":") && !nameParts[0].equals("localhost"))) { return new HostnameReposName(AuthConfig.DEFAULT_SERVER_ADDRESS, reposName); } String hostname = nameParts[0]; reposName = nameParts[1]; if (hostname.contains("index.docker.io")) { throw new InvalidRepositoryNameException(String.format("Invalid repository name, try \"%s\" instead", reposName)); } validateRepoName(reposName); return new HostnameReposName(hostname, reposName); } public static class HostnameReposName { public final String hostname; public final String reposName; public HostnameReposName(String hostname, String reposName) { this.hostname = hostname; this.reposName = reposName; } @Override public boolean equals(Object obj) { if (obj instanceof HostnameReposName) { HostnameReposName other = (HostnameReposName) obj; return new EqualsBuilder().append(hostname, other.hostname).append(reposName, other.reposName) .isEquals(); } else { return false; } } @Override public String toString() { return ToStringBuilder.reflectionToString(this, ToStringStyle.SIMPLE_STYLE); } } }