| @@ -0,0 +1,136 @@ | ||
| /** | ||
| * Copyright [2015] [Christian Loehnert] | ||
| * | ||
| * 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 de.ks.version; | ||
|
|
||
| import org.slf4j.Logger; | ||
| import org.slf4j.LoggerFactory; | ||
|
|
||
| import javax.inject.Inject; | ||
| import java.io.*; | ||
| import java.net.URL; | ||
| import java.util.Optional; | ||
| import java.util.Properties; | ||
| import java.util.jar.Attributes; | ||
| import java.util.jar.Manifest; | ||
|
|
||
| public class DefaultVersionProvider implements VersionProvider { | ||
| public static final String APP_VERSION_KEY = "app.version"; | ||
|
|
||
| private static final Logger log = LoggerFactory.getLogger(DefaultVersionProvider.class); | ||
| private final URL manifestUrl; | ||
| private File versionFile; | ||
|
|
||
| @Inject | ||
| public DefaultVersionProvider(@ManifestMfUrl URL manifestUrl, @VersionFile File versionFile) { | ||
| this.manifestUrl = manifestUrl; | ||
| this.versionFile = versionFile; | ||
| } | ||
|
|
||
| @Override | ||
| public Optional<Integer> getLastVersion() { | ||
| try (FileInputStream stream = new FileInputStream(versionFile)) { | ||
| Properties properties = new Properties(); | ||
| properties.load(stream); | ||
| String value = properties.getProperty(APP_VERSION_KEY, "-1"); | ||
| return Optional.of(Integer.valueOf(value)); | ||
| } catch (IOException e) { | ||
| log.warn("No {} present, will assume version -1", versionFile); | ||
| return Optional.empty(); | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public void writeLastVersion(int version) { | ||
| if (!versionFile.exists()) { | ||
| try { | ||
| versionFile.createNewFile(); | ||
| } catch (IOException e) { | ||
| throw new RuntimeException(e); | ||
| } | ||
| } | ||
|
|
||
| try (FileOutputStream fileOutputStream = new FileOutputStream(versionFile)) { | ||
| Properties properties = new Properties(); | ||
| properties.setProperty(APP_VERSION_KEY, String.valueOf(version)); | ||
| properties.store(fileOutputStream, "42"); | ||
| } catch (IOException e) { | ||
| throw new RuntimeException(e); | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public int getCurrentVersion() { | ||
| String version = getManifestInfo("Implementation-Version"); | ||
| if (version == null) { | ||
| return 0; | ||
| } else { | ||
| int indexOf = version.lastIndexOf("-"); | ||
| if (indexOf > 0) { | ||
| version = version.substring(0, indexOf); | ||
| } | ||
| version = version.replaceAll("\\.", ""); | ||
| return Integer.valueOf(version); | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public String getVersionString() { | ||
| String version = getManifestInfo("Implementation-Version"); | ||
| return version; | ||
| } | ||
|
|
||
| public String getManifestInfo(String key) { | ||
| try { | ||
| InputStream is = manifestUrl.openStream(); | ||
| if (is != null) { | ||
| Manifest manifest = new Manifest(is); | ||
| Attributes mainAttribs = manifest.getMainAttributes(); | ||
| String value = mainAttribs.getValue(key); | ||
| log.debug("From {} {}: {}", manifestUrl, key, value); | ||
| return value; | ||
| } else { | ||
| log.warn("No manifest.mf in {}", manifestUrl); | ||
| } | ||
| } catch (Exception e) { | ||
| log.error("Could not open manifest.mf from {}", manifestUrl, e); | ||
| } | ||
| return null; | ||
| } | ||
|
|
||
| // | ||
| // private URL discoverManifestUrl() { | ||
| // URL ownerLocation = owner.getProtectionDomain().getCodeSource().getLocation(); | ||
| // log.info("Using owner location: '{}'", ownerLocation.getFile()); | ||
| // | ||
| // ArrayList<URL> urlCandidates = new ArrayList<>(); | ||
| // Enumeration resEnum; | ||
| // try { | ||
| // resEnum = Thread.currentThread().getContextClassLoader().getResources(JarFile.MANIFEST_NAME); | ||
| // while (resEnum.hasMoreElements()) { | ||
| // URL url = (URL) resEnum.nextElement(); | ||
| // urlCandidates.add(url); | ||
| // if (url.getFile().contains(ownerLocation.getFile())) { | ||
| // log.info("Found URL to read manifest.mf {}", url); | ||
| // return url; | ||
| // } | ||
| // } | ||
| // } catch (IOException e1) { | ||
| // log.error("Unknown exception ", e1); | ||
| // } | ||
| // log.info("Found no manifest.mf url. Candidates: {}", urlCandidates.stream().map(url -> "\n\t" + url.getFile()).collect(Collectors.toList())); | ||
| // return null; | ||
| // } | ||
| } |
| @@ -1,37 +1,29 @@ | ||
| /** | ||
| * Copyright [2015] [Christian Loehnert] | ||
| * | ||
| * 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 de.ks.version; | ||
|
|
||
| import javax.inject.Qualifier; | ||
| import java.lang.annotation.Retention; | ||
| import java.lang.annotation.Target; | ||
|
|
||
| import static java.lang.annotation.ElementType.*; | ||
| import static java.lang.annotation.RetentionPolicy.RUNTIME; | ||
|
|
||
| @Qualifier | ||
| @Target({FIELD, PARAMETER, METHOD}) | ||
| @Retention(RUNTIME) | ||
| public @interface ManifestMfUrl { | ||
| } |
| @@ -0,0 +1,29 @@ | ||
| /** | ||
| * Copyright [2015] [Christian Loehnert] | ||
| * | ||
| * 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 de.ks.version; | ||
|
|
||
| import javax.inject.Qualifier; | ||
| import java.lang.annotation.Retention; | ||
| import java.lang.annotation.Target; | ||
|
|
||
| import static java.lang.annotation.ElementType.*; | ||
| import static java.lang.annotation.RetentionPolicy.RUNTIME; | ||
|
|
||
| @Qualifier | ||
| @Target({FIELD, PARAMETER, METHOD}) | ||
| @Retention(RUNTIME) | ||
| public @interface VersionFile { | ||
| } |
| @@ -0,0 +1,34 @@ | ||
| /** | ||
| * Copyright [2015] [Christian Loehnert] | ||
| * | ||
| * 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 de.ks.version; | ||
|
|
||
| import com.google.inject.AbstractModule; | ||
|
|
||
| import java.io.File; | ||
| import java.net.URL; | ||
|
|
||
| public abstract class VersionModule extends AbstractModule { | ||
| @Override | ||
| protected void configure() { | ||
| bind(VersionProvider.class).to(DefaultVersionProvider.class); | ||
| bind(URL.class).annotatedWith(ManifestMfUrl.class).toInstance(getManifestUrl()); | ||
| bind(File.class).annotatedWith(VersionFile.class).toInstance(getVersionFile()); | ||
| } | ||
|
|
||
| protected abstract File getVersionFile(); | ||
|
|
||
| protected abstract URL getManifestUrl(); | ||
| } |
| @@ -1,26 +1,31 @@ | ||
| /** | ||
| * Copyright [2015] [Christian Loehnert] | ||
| * | ||
| * 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 de.ks.version; | ||
|
|
||
| import com.google.inject.ImplementedBy; | ||
|
|
||
| import java.util.Optional; | ||
|
|
||
| @ImplementedBy(DefaultVersionProvider.class) | ||
| public interface VersionProvider { | ||
| Optional<Integer> getLastVersion(); | ||
|
|
||
| void writeLastVersion(int version); | ||
|
|
||
| int getCurrentVersion(); | ||
|
|
||
| String getVersionString(); | ||
| } |
| @@ -0,0 +1,43 @@ | ||
| /** | ||
| * Copyright [2015] [Christian Loehnert] | ||
| * | ||
| * 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 de.ks; | ||
|
|
||
| import com.dummy.other.ServiceB; | ||
| import com.google.common.util.concurrent.ThreadFactoryBuilder; | ||
| import com.google.inject.AbstractModule; | ||
| import com.google.inject.Provides; | ||
| import com.google.inject.multibindings.Multibinder; | ||
| import de.ks.launch.Service; | ||
| import de.ks.launch.ServiceA; | ||
|
|
||
| import javax.inject.Singleton; | ||
| import java.util.concurrent.ExecutorService; | ||
| import java.util.concurrent.Executors; | ||
|
|
||
| public class LauncherModule extends AbstractModule { | ||
| @Override | ||
| protected void configure() { | ||
| Multibinder<Service> serviceBinder = Multibinder.newSetBinder(binder(), Service.class); | ||
| serviceBinder.addBinding().to(ServiceA.class).in(Singleton.class); | ||
| serviceBinder.addBinding().to(ServiceB.class).in(Singleton.class); | ||
| } | ||
|
|
||
| @Provides | ||
| @Singleton | ||
| public ExecutorService getExecutor() { | ||
| return Executors.newCachedThreadPool(new ThreadFactoryBuilder().setDaemon(true).setNameFormat("launcher-%d").build()); | ||
| } | ||
| } |
| @@ -0,0 +1,87 @@ | ||
| package de.ks.version; | ||
|
|
||
| import com.google.common.base.StandardSystemProperty; | ||
| import org.junit.Before; | ||
| import org.junit.Test; | ||
|
|
||
| import java.io.File; | ||
| import java.io.IOException; | ||
| import java.net.URL; | ||
| import java.nio.file.Files; | ||
| import java.nio.file.Path; | ||
| import java.nio.file.Paths; | ||
| import java.util.Arrays; | ||
| import java.util.Collections; | ||
| import java.util.List; | ||
| import java.util.Optional; | ||
|
|
||
| import static org.junit.Assert.*; | ||
|
|
||
| public class DefaultVersionProviderTest { | ||
|
|
||
| private DefaultVersionProvider provider; | ||
| private Path manifestPath; | ||
| private Path versionPath; | ||
|
|
||
| @Before | ||
| public void setUp() throws Exception { | ||
| String tempDir = StandardSystemProperty.JAVA_IO_TMPDIR.value(); | ||
| manifestPath = Paths.get(tempDir, "MyManifest.mf"); | ||
| deleteIfExists(manifestPath); | ||
| versionPath = Paths.get(tempDir, "MyVersion.txt"); | ||
| deleteIfExists(versionPath); | ||
|
|
||
| Files.write(manifestPath, Arrays.asList(// | ||
| "Manifest-Version: 1.0",// | ||
| "Implementation-Title: testing",// | ||
| "Implementation-Version: 0.2.3-SNAPSHOT",// | ||
| "Implementation-Vendor: krampenschiesser"// | ||
| )); | ||
|
|
||
| URL manifestMfUrl = manifestPath.toUri().toURL(); | ||
| File versionFile = versionPath.toFile(); | ||
|
|
||
| provider = new DefaultVersionProvider(manifestMfUrl, versionFile); | ||
| } | ||
|
|
||
| private void deleteIfExists(Path path) throws IOException { | ||
| if (Files.exists(path)) { | ||
| Files.delete(path); | ||
| } | ||
| } | ||
|
|
||
| @Test | ||
| public void testWriteVersion() throws Exception { | ||
| provider.writeLastVersion(420); | ||
| assertTrue(Files.exists(versionPath)); | ||
| List<String> lines = Files.readAllLines(versionPath); | ||
| assertEquals(3, lines.size()); | ||
| assertEquals(1, lines.stream().filter(l -> !l.startsWith("#")).count()); | ||
| assertEquals(DefaultVersionProvider.APP_VERSION_KEY + "=420", lines.get(2)); | ||
| } | ||
|
|
||
| @Test | ||
| public void testNoLastVersion() throws Exception { | ||
| Optional<Integer> lastVersion = provider.getLastVersion(); | ||
| assertFalse(lastVersion.isPresent()); | ||
| } | ||
|
|
||
| @Test | ||
| public void testReadLastVersion() throws Exception { | ||
| Files.write(versionPath, Collections.singleton(DefaultVersionProvider.APP_VERSION_KEY + " = 142")); | ||
| int lastVersion = provider.getLastVersion().get(); | ||
| assertEquals(142, lastVersion); | ||
| } | ||
|
|
||
| @Test | ||
| public void testReadFromMetaInf() throws Exception { | ||
| int currentVersion = provider.getCurrentVersion(); | ||
| assertEquals(23, currentVersion); | ||
| } | ||
|
|
||
| @Test | ||
| public void testGetVersionString() throws Exception { | ||
| String versionString = provider.getVersionString(); | ||
| assertEquals("0.2.3-SNAPSHOT", versionString); | ||
| } | ||
| } |