| /* |
| * 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.javaee.wildfly.ide.ui; |
| |
| import java.io.File; |
| |
| import static java.io.File.separatorChar; |
| |
| import java.beans.PropertyVetoException; |
| import java.io.FileInputStream; |
| import java.io.FileReader; |
| import java.io.FilenameFilter; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.net.ServerSocket; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Properties; |
| import java.util.jar.Attributes; |
| import java.util.jar.Manifest; |
| 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.filesystems.JarFileSystem; |
| |
| /** |
| * |
| * @author Ivan Sidorkin |
| */ |
| public class WildflyPluginUtils { |
| |
| public static final Version JBOSS_7_0_0 = new Version("7.0.0", true); // NOI18N |
| |
| public static final Version EAP_6_1_0 = new Version("7.2.0", false); // NOI18N |
| |
| public static final Version EAP_6_2_0 = new Version("7.3.0", false); // NOI18N |
| |
| public static final Version EAP_6_3_0 = new Version("7.4.0", false); // NOI18N |
| |
| public static final Version EAP_6_4_0 = new Version("7.5.0", false); // NOI18N |
| |
| public static final Version EAP_7_0 = new Version("7.0.0", false); // NOI18N |
| |
| public static final Version WILDFLY_8_0_0 = new Version("8.0.0", true); // NOI18N |
| |
| public static final Version WILDFLY_8_1_0 = new Version("8.1.0", true); // NOI18N |
| |
| public static final Version WILDFLY_8_2_0 = new Version("8.2.0", true); // NOI18N |
| |
| public static final Version WILDFLY_9_0_0 = new Version("9.0.0", true); // NOI18N |
| |
| public static final Version WILDFLY_10_0_0 = new Version("10.0.0", true); // NOI18N |
| |
| public static final Version WILDFLY_11_0_0 = new Version("11.0.0", true); // NOI18N |
| |
| public static final Version WILDFLY_12_0_0 = new Version("12.0.0", true); // NOI18N |
| |
| public static final Version WILDFLY_13_0_0 = new Version("13.0.0", true); // NOI18N |
| |
| public static final Version WILDFLY_14_0_0 = new Version("14.0.0", true); // NOI18N |
| |
| public static final Version WILDFLY_15_0_0 = new Version("15.0.0", true); // NOI18N |
| |
| public static final Version WILDFLY_16_0_0 = new Version("16.0.0", true); // NOI18N |
| |
| public static final Version WILDFLY_17_0_0 = new Version("17.0.0", true); // NOI18N |
| |
| public static final Version WILDFLY_18_0_0 = new Version("18.0.0", true); // NOI18N |
| |
| public static final Version WILDFLY_19_0_0 = new Version("19.0.0", true); // NOI18N |
| |
| private static final Logger LOGGER = Logger.getLogger(WildflyPluginUtils.class.getName()); |
| |
| public static final String LIB = "lib" + separatorChar; |
| |
| public static final String MODULES_BASE = "modules" + separatorChar + "system" |
| + separatorChar + "layers" + separatorChar + "base" + separatorChar; |
| |
| public static final String CLIENT = "client" + separatorChar; |
| |
| public static final String COMMON = "common" + separatorChar; |
| |
| //--------------- checking for possible domain directory ------------- |
| private static List<String> domainRequirements; |
| |
| private static synchronized List<String> getDomainRequirements8x() { |
| if (domainRequirements == null) { |
| domainRequirements = new ArrayList<String>(11); |
| Collections.addAll(domainRequirements, |
| "configuration"// NOI18N |
| ); |
| } |
| return domainRequirements; |
| } |
| |
| //--------------- checking for possible server directory ------------- |
| private static List<String> serverRequirements7x; |
| |
| private static synchronized List<String> getServerRequirements8x() { |
| if (serverRequirements7x == null) { |
| serverRequirements7x = new ArrayList<String>(6); |
| Collections.addAll(serverRequirements7x, |
| "bin", // NOI18N |
| "modules", // NOI18N |
| "jboss-modules.jar"); // NOI18N |
| } |
| return serverRequirements7x; |
| } |
| |
| @NonNull |
| public static String getModulesBase(String serverRoot) { |
| return MODULES_BASE; |
| } |
| |
| public static final String getDefaultConfigurationFile(String installDir) { |
| return installDir + File.separatorChar + "standalone" |
| + File.separatorChar + "configuration" |
| + File.separatorChar + "standalone-full.xml"; |
| } |
| |
| //------------ getting exists servers--------------------------- |
| /** |
| * returns Hashmap key = server name value = server folder full path |
| */ |
| public static Map getRegisteredDomains(String serverLocation) { |
| Map result = new HashMap(); |
| File serverDirectory = new File(serverLocation); |
| |
| if (isGoodJBServerLocation(serverDirectory)) { |
| String[] files = new String[]{"standalone"}; |
| File file = serverDirectory; |
| if (files != null) { |
| for (String file1 : files) { |
| String path = file.getAbsolutePath() + separatorChar + file1; |
| if (isGoodJBInstanceLocation(serverDirectory, new File(path))) { |
| result.put(file1, path); |
| } |
| } |
| } |
| } |
| return result; |
| } |
| |
| private static boolean isGoodJBInstanceLocation(File candidate, List<String> requirements) { |
| return null != candidate && candidate.exists() && candidate.canRead() |
| && candidate.isDirectory() |
| && hasRequiredChildren(candidate, requirements); |
| } |
| |
| private static boolean isGoodJBInstanceLocation8x(File serverDir, File candidate) { |
| return isGoodJBInstanceLocation(candidate, getDomainRequirements8x()); |
| } |
| |
| public static boolean isGoodJBInstanceLocation(File serverDir, File candidate) { |
| return WildflyPluginUtils.isGoodJBInstanceLocation8x(serverDir, candidate); |
| } |
| |
| private static boolean isGoodJBServerLocation(File candidate, List<String> requirements) { |
| if (null == candidate |
| || !candidate.exists() |
| || !candidate.canRead() |
| || !candidate.isDirectory() |
| || !hasRequiredChildren(candidate, requirements)) { |
| return false; |
| } |
| return true; |
| } |
| |
| private static boolean isGoodJBServerLocation8x(File candidate) { |
| return isGoodJBServerLocation(candidate, getServerRequirements8x()); |
| } |
| |
| public static boolean isGoodJBServerLocation(File candidate) { |
| return WildflyPluginUtils.isGoodJBServerLocation8x(candidate); |
| } |
| |
| /** |
| * Checks whether the given candidate has all required childrens. Children |
| * can be both files and directories. Method does not distinguish between |
| * them. |
| * |
| * @return true if the candidate has all files/directories named in |
| * requiredChildren, false otherwise |
| */ |
| private static boolean hasRequiredChildren(File candidate, List<String> requiredChildren) { |
| if (null == candidate || null == candidate.list()) { |
| return false; |
| } |
| if (null == requiredChildren) { |
| return true; |
| } |
| |
| for (String next : requiredChildren) { |
| File test = new File(candidate.getPath() + separatorChar + next); |
| if (!test.exists()) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| public static String getDeployDir(String domainDir) { |
| return domainDir + separatorChar + "deployments"; //NOI18N |
| } |
| |
| public static String getHTTPConnectorPort(String configFile) { |
| String defaultPort = "8080"; // NOI18N |
| return defaultPort; |
| } |
| |
| public static String getManagementConnectorPort(String configFile) { |
| String defaultPort = "9990"; // NOI18N |
| return defaultPort; |
| } |
| |
| /** |
| * Return true if the specified port is free, false otherwise. |
| */ |
| public static boolean isPortFree(int port) { |
| ServerSocket soc = null; |
| try { |
| soc = new ServerSocket(port); |
| } catch (IOException ioe) { |
| return false; |
| } finally { |
| if (soc != null) { |
| try { |
| soc.close(); |
| } catch (IOException ex) { |
| } // noop |
| } |
| } |
| |
| return true; |
| } |
| |
| /** |
| * Return the version of the server located at the given path. If the server |
| * version can't be determined returns <code>null</code>. |
| * |
| * @param serverPath path to the server directory |
| * @return specification version of the server |
| */ |
| @CheckForNull |
| public static Version getServerVersion(File serverPath) { |
| assert serverPath != null : "Can't determine version with null server path"; // NOI18N |
| |
| Version version = getProductVersion(serverPath); |
| if (version == null) { |
| File serverDir = new File(serverPath, getModulesBase(serverPath.getAbsolutePath()) + "org/jboss/as/version/main"); |
| File[] files = serverDir.listFiles(new VersionJarFileFilter()); |
| if (files != null) { |
| for (File jarFile : files) { |
| if (jarFile.getName().startsWith("jboss-as-version")) { |
| version = getVersion(jarFile); |
| if (version != null) { |
| break; |
| } |
| } |
| } |
| } |
| } |
| if(version == null) { |
| return WILDFLY_8_0_0; |
| } |
| return version; |
| } |
| |
| /** |
| * Return the version of the server located at the given path. If the server |
| * version can't be determined returns <code>null</code>. |
| * |
| * @param serverPath path to the server directory |
| * @return specification version of the server using product.conf. |
| */ |
| @CheckForNull |
| public static Version getProductVersion(File serverPath) { |
| assert serverPath != null : "Can't determine version with null server path"; // NOI18N |
| String productConf = getProductConf(serverPath); |
| if(productConf != null) { |
| try (FileReader reader = new FileReader(productConf)) { |
| Properties props = new Properties(); |
| props.load(reader); |
| String slot = props.getProperty("slot"); |
| if (slot != null) { |
| File manifestFile = new File(serverPath, getModulesBase(serverPath.getAbsolutePath()) + "org.jboss.as.product".replace('.', separatorChar) + separatorChar + slot + separatorChar + "dir" + separatorChar + "META-INF" + separatorChar + "MANIFEST.MF"); |
| InputStream stream = new FileInputStream(manifestFile); |
| Manifest manifest = new Manifest(stream); |
| String productName = manifest.getMainAttributes().getValue("JBoss-Product-Release-Name"); |
| if(productName == null || productName.isEmpty()) { |
| productName = manifest.getMainAttributes().getValue("JBoss-Project-Release-Name"); |
| } |
| boolean wildfly = productName == null || !productName.toLowerCase().contains("eap"); |
| return new Version(manifest.getMainAttributes().getValue("JBoss-Product-Release-Version"), wildfly); |
| } |
| } catch (Exception e) { |
| // Don't care |
| } |
| } |
| return null; |
| } |
| |
| private static String getProductConf(File serverPath) { |
| final String defaultVal = serverPath.getAbsolutePath() + File.separatorChar + "bin" + File.separatorChar + "product.conf"; |
| String env = System.getenv("JBOSS_PRODUCT_CONF"); |
| if (env == null) { |
| env = defaultVal; |
| } |
| return env; |
| } |
| |
| /** |
| * Check the product name of the server located at the given path. If the server |
| * version can't be determined returns <code>null</code>. |
| * |
| * @param serverPath path to the server directory |
| * @return specification version of the server using product.conf. |
| */ |
| @CheckForNull |
| public static boolean isWildFly(File serverPath) { |
| assert serverPath != null : "Can't determine version with null server path"; // NOI18N |
| String productConf = getProductConf(serverPath); |
| if(productConf != null) { |
| try (FileReader reader = new FileReader(productConf)) { |
| Properties props = new Properties(); |
| props.load(reader); |
| String slot = props.getProperty("slot"); |
| if (slot != null) { |
| File manifestFile = new File(serverPath, getModulesBase(serverPath.getAbsolutePath()) + "org.jboss.as.product".replace('.', separatorChar) + separatorChar + slot + separatorChar + "dir" + separatorChar + "META-INF" + separatorChar + "MANIFEST.MF"); |
| InputStream stream = new FileInputStream(manifestFile); |
| Manifest manifest = new Manifest(stream); |
| String productName = manifest.getMainAttributes().getValue("JBoss-Product-Release-Name"); |
| if(productName == null || productName.isEmpty()) { |
| productName = manifest.getMainAttributes().getValue("JBoss-Project-Release-Name"); |
| } |
| return productName == null || !productName.toLowerCase().contains("eap"); |
| } |
| } catch (Exception e) { |
| LOGGER.log(Level.FINE, "Can't determine version", e); // NOI18N |
| } |
| } |
| return true; |
| } |
| |
| /** |
| * Check the product name of the server located at the given path. If the server |
| * version can't be determined returns <code>null</code>. |
| * |
| * @param serverPath path to the server directory |
| * @return specification version of the server using product.conf. |
| */ |
| @CheckForNull |
| public static boolean isWildFlyServlet(File serverPath) { |
| assert serverPath != null : "Can't determine version with null server path"; // NOI18N |
| String productConf = getProductConf(serverPath); |
| if(productConf != null) { |
| File productConfFile = new File(productConf); |
| if(productConfFile.exists() && productConfFile.canRead()) { |
| try (FileReader reader = new FileReader(productConf)) { |
| Properties props = new Properties(); |
| props.load(reader); |
| String slot = props.getProperty("slot"); |
| if (slot != null) { |
| File manifestFile = new File(serverPath, getModulesBase(serverPath.getAbsolutePath()) + "org.jboss.as.product".replace('.', separatorChar) + separatorChar + slot + separatorChar + "dir" + separatorChar + "META-INF" + separatorChar + "MANIFEST.MF"); |
| InputStream stream = new FileInputStream(manifestFile); |
| Manifest manifest = new Manifest(stream); |
| String productName = manifest.getMainAttributes().getValue("JBoss-Product-Release-Name"); |
| if(productName == null || productName.isEmpty()) { |
| productName = manifest.getMainAttributes().getValue("JBoss-Project-Release-Name"); |
| } |
| return productName != null && (productName.contains("WildFly Web Lite") || productName.contains("WildFly Servlet")); |
| } |
| } catch (Exception e) { |
| LOGGER.log(Level.INFO, "Can't determine version", e); // NOI18N |
| } |
| } |
| } |
| return false; |
| } |
| |
| private static class VersionJarFileFilter implements FilenameFilter { |
| |
| @Override |
| public boolean accept(File dir, String name) { |
| return name.endsWith(".jar") && (name.startsWith("jboss-as-version") || name.startsWith("wildfly-version")); |
| } |
| } |
| |
| private static Version getVersion(File systemJarFile) { |
| if (!systemJarFile.exists()) { |
| return null; |
| } |
| |
| try { |
| JarFileSystem systemJar = new JarFileSystem(); |
| systemJar.setJarFile(systemJarFile); |
| Attributes attributes = systemJar.getManifest().getMainAttributes(); |
| String version = attributes.getValue("Specification-Version"); // NOI18N |
| if (version != null) { |
| return new Version(version, true); |
| } |
| return null; |
| } catch (IOException | PropertyVetoException ex) { |
| LOGGER.log(Level.INFO, null, ex); |
| return null; |
| } |
| } |
| |
| /** |
| * Class representing the JBoss version. |
| * <p> |
| * <i>Immutable</i> |
| * |
| * @author Petr Hejl |
| */ |
| public static final class Version implements Comparable<Version> { |
| |
| private String majorNumber = "0"; |
| |
| private String minorNumber = "0"; |
| |
| private String microNumber = "0"; |
| |
| private String update = ""; |
| |
| private boolean wildfly = true; |
| |
| /** |
| * Constructs the version from the spec version string. Expected format |
| * is <code>MAJOR_NUMBER[.MINOR_NUMBER[.MICRO_NUMBER[.UPDATE]]]</code>. |
| * |
| * @param version spec version string with the following format: |
| * <code>MAJOR_NUMBER[.MINOR_NUMBER[.MICRO_NUMBER[.UPDATE]]]</code> |
| */ |
| public Version(String version, boolean wildfly) { |
| assert version != null : "Version can't be null"; // NOI18N |
| this.wildfly = wildfly; |
| String[] tokens = version.split("\\."); |
| |
| if (tokens.length >= 4) { |
| update = tokens[3]; |
| } |
| if (tokens.length >= 3) { |
| microNumber = tokens[2]; |
| } |
| if (tokens.length >= 2) { |
| minorNumber = tokens[1]; |
| } |
| majorNumber = tokens[0]; |
| } |
| |
| /** |
| * Returns the major number. |
| * |
| * @return the major number. Never returns <code>null</code>. |
| */ |
| public String getMajorNumber() { |
| return majorNumber; |
| } |
| |
| /** |
| * Returns the minor number. |
| * |
| * @return the minor number. Never returns <code>null</code>. |
| */ |
| public String getMinorNumber() { |
| return minorNumber; |
| } |
| |
| /** |
| * Returns the micro number. |
| * |
| * @return the micro number. Never returns <code>null</code>. |
| */ |
| public String getMicroNumber() { |
| return microNumber; |
| } |
| |
| /** |
| * Returns the update. |
| * |
| * @return the update. Never returns <code>null</code>. |
| */ |
| public String getUpdate() { |
| return update; |
| } |
| |
| /** |
| * {@inheritDoc} |
| * <p> |
| * Two versions are equal if and only if they have same major, minor, |
| * micro number and update. |
| */ |
| @Override |
| public boolean equals(Object obj) { |
| // XXX thiw want match compareTo contract in case there will be numbers like "1" and "01". |
| if (obj == null) { |
| return false; |
| } |
| if (getClass() != obj.getClass()) { |
| return false; |
| } |
| final Version other = (Version) obj; |
| if (this.majorNumber != other.majorNumber |
| && (this.majorNumber == null || !this.majorNumber.equals(other.majorNumber))) { |
| return false; |
| } |
| if (this.minorNumber != other.minorNumber |
| && (this.minorNumber == null || !this.minorNumber.equals(other.minorNumber))) { |
| return false; |
| } |
| if (this.microNumber != other.microNumber |
| && (this.microNumber == null || !this.microNumber.equals(other.microNumber))) { |
| return false; |
| } |
| if (this.update != other.update |
| && (this.update == null || !this.update.equals(other.update))) { |
| return false; |
| } |
| if(this.wildfly != other.wildfly) { |
| return false; |
| } |
| return true; |
| } |
| |
| public boolean isWidlfy() { |
| return wildfly; |
| } |
| |
| /** |
| * {@inheritDoc} |
| * <p> |
| * The implementation consistent with {@link #equals(Object)}. |
| */ |
| @Override |
| public int hashCode() { |
| int hash = 7; |
| hash = 17 * hash + (this.majorNumber != null ? this.majorNumber.hashCode() : 0); |
| hash = 17 * hash + (this.minorNumber != null ? this.minorNumber.hashCode() : 0); |
| hash = 17 * hash + (this.microNumber != null ? this.microNumber.hashCode() : 0); |
| hash = 17 * hash + (this.update != null ? this.update.hashCode() : 0); |
| return hash; |
| } |
| |
| /** |
| * {@inheritDoc} |
| * <p> |
| * Compares the versions based on its major, minor, micro and update. |
| * Major number is the most significant. Implementation is consistent |
| * with {@link #equals(Object)}. |
| */ |
| @Override |
| public int compareTo(Version o) { |
| int comparison = compareToIgnoreUpdate(o); |
| if (comparison != 0) { |
| return comparison; |
| } |
| return update.compareTo(o.update); |
| } |
| |
| /** |
| * Compares the versions based on its major, minor, micro. Update field |
| * is ignored. Major number is the most significant. |
| * |
| * @param o version to compare with |
| */ |
| public int compareToIgnoreUpdate(Version o) { |
| if (o == null) { |
| return 1; |
| } |
| if(this.wildfly != o.wildfly) { |
| return convertEAP(this).compareToIgnoreUpdate(convertEAP(o)); |
| |
| } |
| int comparison = compare(majorNumber, o.majorNumber); |
| if (comparison != 0) { |
| return comparison; |
| } |
| comparison = compare(minorNumber, o.minorNumber); |
| if (comparison != 0) { |
| return comparison; |
| } |
| return compare(microNumber, o.microNumber); |
| } |
| |
| private Version convertEAP(Version version) { |
| if (!version.isWidlfy()) { |
| if (version.compareToIgnoreUpdate(EAP_7_0) >= 0) { |
| return WILDFLY_10_0_0; |
| } |
| return JBOSS_7_0_0; |
| } |
| return version; |
| } |
| |
| private int compare(String number1, String number2) { |
| if (number1.length() != number2.length()) { |
| try { |
| Integer i1 = Integer.parseInt(number1); |
| Integer i2 = Integer.parseInt(number2); |
| return i1.compareTo(i2); |
| } catch (NumberFormatException ex) { |
| // compare as strings below |
| } |
| } |
| return number1.compareTo(number2); |
| } |
| |
| @Override |
| public String toString() { |
| return "Version{" + (wildfly ? "WILDFLY " : "EAP ") + "majorNumber=" + majorNumber + ", minorNumber=" + minorNumber + ", microNumber=" + microNumber + ", update=" + update + '}'; |
| } |
| |
| } |
| |
| } |