001/* 002 * Copyright 2012-2015 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.boot.autoconfigure.condition; 018 019import java.lang.annotation.Documented; 020import java.lang.annotation.ElementType; 021import java.lang.annotation.Retention; 022import java.lang.annotation.RetentionPolicy; 023import java.lang.annotation.Target; 024 025import org.springframework.context.annotation.Conditional; 026import org.springframework.util.Assert; 027import org.springframework.util.ClassUtils; 028 029/** 030 * {@link Conditional} that matches based on the JVM version the application is running 031 * on. 032 * 033 * @author Oliver Gierke 034 * @author Phillip Webb 035 * @author Andy Wilkinson 036 * @since 1.1.0 037 */ 038@Target({ ElementType.TYPE, ElementType.METHOD }) 039@Retention(RetentionPolicy.RUNTIME) 040@Documented 041@Conditional(OnJavaCondition.class) 042public @interface ConditionalOnJava { 043 044 /** 045 * Configures whether the value configured in {@link #value()} shall be considered the 046 * upper exclusive or lower inclusive boundary. Defaults to 047 * {@link Range#EQUAL_OR_NEWER}. 048 * @return the range 049 */ 050 Range range() default Range.EQUAL_OR_NEWER; 051 052 /** 053 * The {@link JavaVersion} to check for. Use {@link #range()} to specify whether the 054 * configured value is an upper-exclusive or lower-inclusive boundary. 055 * @return the java version 056 */ 057 JavaVersion value(); 058 059 /** 060 * Range options. 061 */ 062 enum Range { 063 064 /** 065 * Equal to, or newer than the specified {@link JavaVersion}. 066 */ 067 EQUAL_OR_NEWER, 068 069 /** 070 * Older than the specified {@link JavaVersion}. 071 */ 072 OLDER_THAN 073 074 } 075 076 /** 077 * Java versions. 078 */ 079 enum JavaVersion { 080 081 /** 082 * Java 1.9. 083 */ 084 NINE(9, "1.9", "java.security.cert.URICertStoreParameters"), 085 086 /** 087 * Java 1.8. 088 */ 089 EIGHT(8, "1.8", "java.util.function.Function"), 090 091 /** 092 * Java 1.7. 093 */ 094 SEVEN(7, "1.7", "java.nio.file.Files"), 095 096 /** 097 * Java 1.6. 098 */ 099 SIX(6, "1.6", "java.util.ServiceLoader"); 100 101 private final int value; 102 103 private final String name; 104 105 private final boolean available; 106 107 JavaVersion(int value, String name, String className) { 108 this.value = value; 109 this.name = name; 110 this.available = ClassUtils.isPresent(className, getClass().getClassLoader()); 111 } 112 113 /** 114 * Determines if this version is within the specified range of versions. 115 * @param range the range 116 * @param version the bounds of the range 117 * @return if this version is within the specified range 118 */ 119 public boolean isWithin(Range range, JavaVersion version) { 120 Assert.notNull(range, "Range must not be null"); 121 Assert.notNull(version, "Version must not be null"); 122 switch (range) { 123 case EQUAL_OR_NEWER: 124 return this.value >= version.value; 125 case OLDER_THAN: 126 return this.value < version.value; 127 } 128 throw new IllegalStateException("Unknown range " + range); 129 } 130 131 @Override 132 public String toString() { 133 return this.name; 134 } 135 136 /** 137 * Returns the {@link JavaVersion} of the current runtime. 138 * @return the {@link JavaVersion} 139 */ 140 public static JavaVersion getJavaVersion() { 141 for (JavaVersion candidate : JavaVersion.values()) { 142 if (candidate.available) { 143 return candidate; 144 } 145 } 146 return SIX; 147 } 148 149 } 150 151}