blob: 81845e00160e5ee5895890ba161ca69fc97bd72d [file] [log] [blame]
/*
* 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.netbeans.modules.payara.tooling.data;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.api.annotations.common.CheckForNull;
import org.netbeans.api.annotations.common.NonNull;
import org.openide.util.Exceptions;
import org.apache.maven.artifact.repository.metadata.Metadata;
import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;
import org.netbeans.modules.maven.indexer.api.RepositoryInfo;
import org.netbeans.modules.maven.indexer.api.RepositoryPreferences;
import org.openide.util.NbBundle;
/**
* Payara Platform version.
* <p/>
* @author Tomas Kraus, Peter Benedikovic
* @author Gaurav Gupta
*/
public class PayaraPlatformVersion implements PayaraPlatformVersionAPI, Comparable<PayaraPlatformVersionAPI> {
////////////////////////////////////////////////////////////////////////////
// Class attributes //
////////////////////////////////////////////////////////////////////////////
private static final Logger LOGGER = Logger.getLogger(PayaraPlatformVersion.class.getName());
/**
* Payara Server artifact download url
*/
private static final String DOWNLOAD_URL = "fish/payara/distributions/payara/%s/payara-%s.zip"; // NOI18N
public static final String DEFAULT_REPOSITORY_URL = "https://repo1.maven.org/maven2/"; // NOI18N
private static final String METADATA_URL = "fish/payara/distributions/payara/maven-metadata.xml"; // NOI18N
private static final String LOCAL_METADATA_URL = "fish/payara/distributions/payara/maven-metadata-local.xml"; // NOI18N
private static final String CDDL_LICENSE = "https://raw.githubusercontent.com/payara/Payara/master/LICENSE.txt"; // NOI18N
public static final PayaraPlatformVersionAPI EMPTY = new PayaraPlatformVersion((short) 0, (short) 0, (short) 0, (short) 0, "", "", "");
private static PayaraPlatformVersionAPI latestVersion;
private static final Map<String, PayaraPlatformVersionAPI> versions = new TreeMap<>();
public static PayaraPlatformVersionAPI getLatestVersion() {
if (!getVersions().isEmpty()) {
return latestVersion;
} else {
return null;
}
}
public static Map<String, PayaraPlatformVersionAPI> getVersionMap() {
if (!getVersions().isEmpty()) {
return Collections.unmodifiableMap(versions);
} else {
return Collections.emptyMap();
}
}
public static List<PayaraPlatformVersionAPI> getVersions() {
if (versions.isEmpty()) {
String repository = DEFAULT_REPOSITORY_URL;
boolean readDefaultRepo;
URL metadata;
try {
metadata = new URL(repository + METADATA_URL);
readDefaultRepo = readVersions(repository, metadata);
} catch (UnknownHostException ex) {
readDefaultRepo = false;
LOGGER.log(Level.INFO, repository, ex);
} catch (Exception ex) {
readDefaultRepo = false;
Exceptions.printStackTrace(ex);
}
if (!readDefaultRepo) {
for (RepositoryInfo info : RepositoryPreferences.getInstance().getRepositoryInfos()) {
try {
repository = info.getRepositoryUrl();
if (repository != null) {
metadata = new URL(repository + METADATA_URL);
} else {
repository = new File(info.getRepositoryPath() + File.separator).toURI().toString();
if(!new File(repository + LOCAL_METADATA_URL).exists()) {
continue;
}
metadata = new URL(repository + LOCAL_METADATA_URL);
}
if (readVersions(repository, metadata)) {
break;
}
} catch (UnknownHostException ex) {
LOGGER.log(Level.INFO, repository, ex);
} catch (Exception ex) {
Exceptions.printStackTrace(ex);
}
}
}
}
return new ArrayList<>(versions.values());
}
private static boolean readVersions(String repository, URL metadata) throws Exception {
try (InputStream input = metadata.openStream()) {
MetadataXpp3Reader reader = new MetadataXpp3Reader();
Metadata data = reader.read(new InputStreamReader(input));
versions.clear();
for (String version : data.getVersioning().getVersions()) {
if (version.contains("Alpha") || version.contains("Beta") || version.contains("SNAPSHOT")) { // NOI18N
continue;
}
PayaraPlatformVersionAPI payaraVersion = PayaraPlatformVersion.toValue(repository, version);
versions.put(version, payaraVersion);
if (version.equals(data.getVersioning().getLatest())) {
latestVersion = payaraVersion;
}
}
if (!versions.isEmpty()) {
return true;
}
}
return false;
}
public static List<PayaraPlatformVersionAPI> getVersions(String repository) {
return new ArrayList<>(versions.values());
}
@CheckForNull
public static PayaraPlatformVersionAPI toValue(
@NonNull final String versionStr) {
return toValue(DEFAULT_REPOSITORY_URL, versionStr);
}
/**
* Returns a <code>PayaraPlatformVersionAPI</code> with a value represented by the
* specified <code>String</code>. The <code>PayaraPlatformVersionAPI</code> returned
* represents existing value only if specified <code>String</code> matches
* any <code>String</code> returned by <code>toString</code> method.
* Otherwise <code>null</code> value is returned.
* <p/>
* @param repository Value containing maven repository url <code>String</code>
* @param versionStr Value containing version <code>String</code>
* representation.
* @return <code>PayaraPlatformVersionAPI</code> value represented by
* <code>String</code> or <code>null</code> if value was not recognized.
*/
@CheckForNull
public static PayaraPlatformVersionAPI toValue(
@NonNull final String repository,
@NonNull final String versionStr) {
if(versionStr.trim().isEmpty()) {
return EMPTY;
}
PayaraPlatformVersionAPI version
= versions.get(versionStr.toUpperCase(Locale.ENGLISH));
if (version == null) {
String[] versionComps = versionStr.split(SEPARATOR_PATTERN);
short major = Short.valueOf(versionComps[0]);
short minor = Short.valueOf(versionComps[1]);
short update = 0, build = 0;
if (versionComps.length > 2) {
update = Short.valueOf(versionComps[2]);
}
if (versionComps.length > 3) {
build = Short.valueOf(versionComps[3]);
}
version = new PayaraPlatformVersion(
major, minor, update, build,
major >= 5 ? "deployer:pfv5ee8" : "deployer:pfv4ee7",
repository, versionStr
);
}
return version;
}
////////////////////////////////////////////////////////////////////////////
// Instance attributes //
////////////////////////////////////////////////////////////////////////////
/**
* Major version number.
*/
private final short major;
/**
* Minor version number.
*/
private final short minor;
/**
* Update version number.
*/
private final short update;
/**
* Build version number.
*/
private final short build;
private final String uriFragment;
private final String indirectUrl;
private final String directUrl;
private final String value;
////////////////////////////////////////////////////////////////////////////
// Constructors //
////////////////////////////////////////////////////////////////////////////
/**
* Constructs an instance of Payara server version.
* <p/>
* @param major Major version number.
* @param minor Minor version number.
* @param update Update version number.
* @param build Build version number.
*/
private PayaraPlatformVersion(final short major, final short minor,
final short update, final short build, String uriFragment,
final String repository, final String value) {
this.major = major;
this.minor = minor;
this.update = update;
this.build = build;
this.uriFragment = uriFragment;
this.value = value;
this.indirectUrl = null;
this.directUrl = repository + String.format(DOWNLOAD_URL, value, value);
}
////////////////////////////////////////////////////////////////////////////
// Getters //
////////////////////////////////////////////////////////////////////////////
/**
* Get major version number.
*
* @return Major version number.
*/
@Override
public short getMajor() {
return major;
}
/**
* Get minor version number.
* <p/>
* @return Minor version number.
*/
@Override
public short getMinor() {
return minor;
}
/**
* Get update version number.
* <p/>
* @return Update version number.
*/
@Override
public short getUpdate() {
return update;
}
/**
* Get build version number.
* <p/>
* @return Build version number.
*/
@Override
public short getBuild() {
return build;
}
@Override
public String getUriFragment() {
return uriFragment;
}
@Override
public String getDirectUrl() {
return directUrl;
}
@Override
public String getIndirectUrl() {
return indirectUrl;
}
@Override
public String getLicenseUrl() {
return CDDL_LICENSE;
}
@Override
public boolean isMinimumSupportedVersion() {
return major >= 4;
}
@Override
public boolean isEE7Supported() {
return major >= 4;
}
@Override
public boolean isEE8Supported() {
return major >= 5;
}
////////////////////////////////////////////////////////////////////////////
// Methods //
////////////////////////////////////////////////////////////////////////////
/**
* Compare major and minor parts of version number <code>String</code>s.
* <p/>
* @param version Payara server version to compare with this object.
* @return Value of <code>true</code> when major and minor parts of version
* numbers are the same or <code>false</code> otherwise.
*/
@Override
public boolean equalsMajorMinor(final PayaraPlatformVersionAPI version) {
if (version == null) {
return false;
} else {
return this.major == version.getMajor() && this.minor == version.getMinor();
}
}
/**
* Compare all parts of version number <code>String</code>s.
* <p/>
* @param version Payara server version to compare with this object.
* @return Value of <code>true</code> when all parts of version numbers are
* the same or <code>false</code> otherwise.
*/
@SuppressWarnings("AccessingNonPublicFieldOfAnotherObject")
@Override
public boolean equals(final PayaraPlatformVersionAPI version) {
if (version == null) {
return false;
} else {
return this.major == version.getMajor()
&& this.minor == version.getMinor()
&& this.update == version.getUpdate()
&& this.build == version.getBuild();
}
}
/**
* Convert <code>PayaraPlatformVersionAPI</code> value to <code>String</code>.
* <p/>
* @return A <code>String</code> representation of the value of this object.
*/
@Override
public String toString() {
return value;
}
/**
* Convert <code>PayaraPlatformVersionAPI</code> value to <code>String</code>
* containing all version numbers.
* <p/>
* @return A <code>String</code> representation of the value of this object
* containing all version numbers.
*/
public String toFullString() {
StringBuilder sb = new StringBuilder(8);
sb.append(Integer.toString(major));
sb.append(SEPARATOR);
sb.append(Integer.toString(minor));
sb.append(SEPARATOR);
sb.append(Integer.toString(update));
sb.append(SEPARATOR);
sb.append(Integer.toString(build));
return sb.toString();
}
@Override
public int compareTo(PayaraPlatformVersionAPI o) {
return Comparator.comparing(PayaraPlatformVersionAPI::getMajor)
.thenComparing(PayaraPlatformVersionAPI::getMinor)
.thenComparingInt(PayaraPlatformVersionAPI::getUpdate)
.thenComparingInt(PayaraPlatformVersionAPI::getBuild)
.compare(this, o);
}
}