summaryrefslogblamecommitdiffstats
path: root/dozentenmodul/src/main/java/org/openslx/dozmod/util/ClientVersion.java
blob: d6d35cd480e46e92ad8b5c2921ecbe4427326f4f (plain) (tree)
1
2
3
4
5
6
7
8
9

                                
                           
                    
                                         


                                
                                                          
                               
                             
 



                                                                                   


                                                   

                                                    
 
                                    











                                                                                
         
 
           
                                                                            



                                                 
                       

                                     
 


                  
                                                   
                       

                                         
 


                                                            
                                                                  

                                                  
                       
                                      
         
 





                                                                       
                       
                                          
         
 
           
                                                          


                                                                     
                                          




                                                                                                          

                                                               
         
 



                                                                         
                                                
                                                                 


                                                                           

                                             
                 
                                                                                                     
                                         

                                                                               
                                       



                                                                           
                 








                                                                              



                                                                         
                                                                                          

                                                                          
                 
                                          
                                                    
                 
                                              





                                                                                          
                 
         
 
           
                                                                             


                                                                        
                                            

                                                                       
                                   




                                                                                        
                                       



                                                                                  

                 



                                                                                

         



                                      
                               
                                
                                 

         
package org.openslx.dozmod.util;

import java.io.InputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.jar.Attributes;
import java.util.jar.Manifest;

import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.log4j.Logger;
import org.openslx.util.Json;

// ClientVersion is a bad name, TODO find better suited one :)
public class ClientVersion {

	private static final Logger LOGGER = Logger.getLogger(ClientVersion.class);

	private static long localRevisionTime = 0;
	private static long remoteRevisionTime = 0;
	private static String localRevision = null;
	private static String remoteRevision = null;

	private static void init() {
		if (localRevision == null) {
			loadLocalVersion();
		}
		if (localRevision == null) {
			localRevision = "???";
		}
		if (remoteRevision == null) {
			loadRemoteVersion("http://132.230.4.25/dozmod.version");
		}
		if (remoteRevision == null) {
			remoteRevision = "???";
		}
	}

	/**
	 * Gets the local revision id if loading it worked, "???" otherwise.
	 * 
	 * @return id as String
	 */
	public static String getLocalRevision() {
		init();
		return localRevision;
	}

	/**
	 * @return
	 */
	public static long getLocalRevTimestamp() {
		init();
		return localRevisionTime;
	}

	/**
	 * Gets the revision id of the latest remote version
	 * 
	 * @return id as String if loading worked, "???" otherwise
	 */
	public static String getRemoteRevision() {
		init();
		return remoteRevision;
	}

	/**
	 * Gets the timestamp of the latest remote version
	 * 
	 * @return timestamp as Long if loading it worked, 0L otherwise
	 */
	public static long getRemoteRevTimestamp() {
		init();
		return remoteRevisionTime;
	}

	/**
	 * Checks if we are running latest bwSuite version
	 * 
	 * @return true if there is no newer version, false otherwise
	 */
	public static boolean isNewest() {
		init();
		// if either local or remote version is unknown, just pretend there's no update
		// as there most likely isn't and we'd just annoy the user
		// TODO: Report "fail" state so at least on manual update check we can tell that it failed
		if (localRevisionTime == 0 || remoteRevisionTime == 0)
			return true;
		return localRevisionTime >= remoteRevisionTime;
	}

	/**
	 * Loads the local version information from the jar's MANIFEST.MF
	 * into the fields 'localRevision' and 'localRevisionTime'
	 */
	private static void loadLocalVersion() {
		Class<ClientVersion> clazz = ClientVersion.class;
		String className = clazz.getSimpleName() + ".class";
		String classPath = clazz.getResource(className).toString();
		if (!classPath.startsWith("jar")) {
			// Class not from JAR
			return;
		}
		String manifestPath = classPath.replaceAll("![^!]*$", "") + "!/META-INF/MANIFEST.MF";
		Manifest manifest = null;
		try (InputStream stream = new URL(manifestPath).openStream()) {
			manifest = new Manifest(stream);
		} catch (Exception e) {
			if (manifest == null) {
				LOGGER.error("Could not open MANIFEST", e);
				return;
			}
		}
		Attributes attributes = manifest.getMainAttributes();
		// if attr are null, then we couldn't open the jar's MANIFEST
		// since we are probably not in a jar context, just do nothing
		if (attributes == null)
			return;
		String manifestRev = null;
		String manifestRevTime = null;
		try {
			manifestRev = attributes.getValue("Build-Revision");
		} catch (Exception e) {
			LOGGER.warn("Error while reading revision: ", e);
		}
		try {
			manifestRevTime = attributes.getValue("Build-Revision-Timestamp");
		} catch (Exception e) {
			LOGGER.warn("Error while reading timestamp: ", e);
		}
		if (manifestRev != null) {
			localRevision = manifestRev;
		}
		if (manifestRevTime != null) {
			try {
				// hax since we get milliseconds not seconds
				localRevisionTime = Long.valueOf(manifestRevTime) / 1000L;
			} catch (NumberFormatException e) {
				LOGGER.warn("Build timestamp is not a number!", e);
			}
		}
	}

	/**
	 * Loads the given UrlString as JSON and saves the remote information
	 * into fields 'remoteRevision' and 'remoteRevisionTime'
	 * 
	 * The remote JSON should have 'timestamp' and 'revision', like:
	 * { "timestamp": 1, "revision": 2 }
	 */
	private static void loadRemoteVersion(final String urlString) {
		String json = null;
		try (InputStream reader = new URL(urlString).openStream()) {
			ByteArrayOutputStream buffer = new ByteArrayOutputStream();
			buffer.write(reader);
			buffer.close();
			json = new String(buffer.toByteArray(), StandardCharsets.UTF_8);
		} catch (Exception e) {
			if (json == null) {
				LOGGER.error("Could not fetch remote version", e);
				return;
			}
		}

		VersionQuery query = Json.deserialize(json, VersionQuery.class);
		remoteRevision = query.revision;
		// seconds timestamp here...
		remoteRevisionTime = query.timestamp;
	}

	/**
	 * Class for GSON json parsing
	 */
	static class VersionQuery {
		long timestamp;
		String revision;
//		String changelog;
	}
}