blob: 48c672b3ebf964a33d38d8075d7d12d666045bf7 [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.apache.axis2.jaxws.util;
import org.apache.axis2.java.security.AccessController;
import org.apache.axis2.jaxws.ExceptionFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.io.IOException;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Properties;
import java.util.StringTokenizer;
public class WSToolingUtils {
private static final Log log = LogFactory.getLog(WSToolingUtils.class);
/**
* A handy function to check for empty or null string
*
* @param str
* @return boolean
*
*/
public static boolean hasValue(String str) {
return ((str != null) && (str.length() > 0));
}
/**
* Retrieves the major version number of the WsGen class that we're using
*
* @return String
*
*/
public static String getWsGenVersion() throws ClassNotFoundException, IOException {
Class clazz = null;
try {
clazz = forName("com.sun.tools.ws.WsGen", false,
getContextClassLoader(null));
} catch (ClassNotFoundException e1) {
try {
clazz = forName("com.sun.tools.internal.ws.WsGen", false,
getContextClassLoader(null));
} catch (ClassNotFoundException e2) {
if (log.isDebugEnabled()) {
log.debug("Exception thrown from getWsGenVersion: " + e2.getMessage(), e2);
}
throw (ClassNotFoundException) e2;
}
}
Properties p = new Properties();
try {
p.load(clazz.getResourceAsStream("version.properties"));
} catch (IOException ioex) {
if (log.isDebugEnabled()) {
log.debug("Exception thrown from getWsGenVersion: " + ioex.getMessage(), ioex);
}
throw (IOException) ioex.getCause();
}
return (p.getProperty("major-version"));
}
/**
* @return ClassLoader
*/
private static ClassLoader getContextClassLoader(final ClassLoader classLoader) {
ClassLoader cl;
try {
cl = (ClassLoader) AccessController.doPrivileged(
new PrivilegedExceptionAction() {
public Object run() throws ClassNotFoundException {
return classLoader != null ? classLoader : Thread.currentThread().getContextClassLoader();
}
}
);
} catch (PrivilegedActionException e) {
if (log.isDebugEnabled()) {
log.debug("Exception thrown from AccessController: " + e.getMessage(), e);
}
throw ExceptionFactory.makeWebServiceException(e.getException());
}
return cl;
}
/**
* Return the class for this name
*
* @return Class
*/
private static Class forName(final String className, final boolean initialize,
final ClassLoader classloader) throws ClassNotFoundException {
Class cl = null;
try {
cl = (Class) AccessController.doPrivileged(
new PrivilegedExceptionAction() {
public Object run() throws ClassNotFoundException {
return Class.forName(className, initialize, classloader);
}
}
);
} catch (PrivilegedActionException e) {
if (log.isDebugEnabled()) {
log.debug("Exception thrown from AccessController: " + e.getMessage(), e);
}
throw (ClassNotFoundException) e.getException();
}
return cl;
}
/**
* Answer if the input version number is 2.1.6 or later. Version 2.1.6 is the Sun RI version that changed
* the WebMethod annotation semantics.
*
* @param wsGenVersion A version number separated by "." Up to the first 3 values will be checked.
* @return true if the version number is 2.1.6 or later, false otherwise.
*/
public static boolean isValidVersion(String wsGenVersion) {
if(log.isDebugEnabled()){
log.debug("Start isValidVersion(String)");
}
if (log.isDebugEnabled()) {
log.debug("isValidVersion: Determining if WsGen version: " +wsGenVersion
+" is appropriate version for using new SUN RI behavior");
}
if(wsGenVersion == null){
return false;
}
/*
* This algorithm is improvement over the old algorithm we had to validate the
* version. In this algorithm we don't assume that the format will be x.x.x.
* This algorithm looks for versionNumbers in a String token delimited by a
* ".", the idea is to look for the first digit in each token and compare that
* with the version validation requirements.
* we return false if version is less that 2.1.6.
* possible input version strings could be "JAX-WS RI 2.2-b05-", "2.1.6" "2.1.0" etc.
*/
// Minimum version required is 2.1.6
final int minimumVersionRequired[] = {2, 1, 6};
String version = wsGenVersion.trim();
StringTokenizer st = new StringTokenizer(version, ".");
if(st.countTokens() <= 0){
if(log.isDebugEnabled()){
log.debug("No Tokens to validate the tooling version, Input version String is invalid.");
}
return false;
}
// Check up to as many version values as we have values in the minimum required version
boolean lastCheckEqual = false;
int tokenCnt = 0;
for( ; tokenCnt < minimumVersionRequired.length && st.hasMoreTokens(); tokenCnt++) {
String token = st.nextToken();
if(token == null){
return false;
}
int versionNumber = getIntegerValue(token);
int minimumVersionNumber = minimumVersionRequired[tokenCnt];
if (versionNumber < minimumVersionNumber) {
// The version number is too low, so it is invalid
if(log.isDebugEnabled()){
log.debug("Validation failed on tokenCnt = " + tokenCnt);
log.debug("Input VersionNumber =" + versionNumber);
log.debug("Minimum Version Number required = " + minimumVersionNumber);
}
return false;
} else if (versionNumber > minimumVersionNumber) {
// The version number is higher than required, so it passes validation.
if(log.isDebugEnabled()){
log.debug("Validation passed on tokenCnt = " + tokenCnt);
log.debug("Input VersionNumber = " + versionNumber);
log.debug("Minimum Version Number required = " + minimumVersionNumber);
}
return true;
} else {
// The version number sub-value matches exactly, so we need to check the next sub-value.s
if(log.isDebugEnabled()){
log.debug("Validation unresolved on tokenCnt = " + tokenCnt);
log.debug("Input VersionNumber = " + versionNumber);
log.debug("Minimum Version Number required = " + minimumVersionNumber);
}
lastCheckEqual = true;
continue;
}
}
if(log.isDebugEnabled()){
log.debug("Exit isValidVersion(String)");
}
// If the version numbers we checked so far were equal to the minimum version BUT it was shorter
// in length, then return false. For example if the input is "2.1", that is actually "2.1.0"
// which would be less than "2.1.6".
if (lastCheckEqual && tokenCnt < minimumVersionRequired.length) {
return false;
}
return true;
}
/**
* Parse the input string and return an integer value based on it. It will look for the first numeric value
* in the string then use all digits up to the next non-numeric value or end of the string as the basis for
* the value. For example "JAX-WS RI 27" will return the value 27.
* @param s - String containing the integer to be returned.
* @return a value or -1 if not integer value was found in the token.
*/
private static int getIntegerValue(String s){
int returnValue = -1;
// Build up a buffer containing any digits up to the first non-numeric character.
StringBuffer valueString = new StringBuffer();
for(int i = 0; i < s.length(); i++){
char ch = s.charAt(i);
if(Character.isDigit(ch)){
valueString.append(Character.getNumericValue(ch));
} else if (valueString.length() > 0){
// We've found some numbers then encountered the first non-numeric value, so
// exit the loop and use those numbers as the value
break;
}
}
// If there were any numeric values found in the string, convert them to the integer return value
if (valueString.length() > 0) {
returnValue = Integer.valueOf(valueString.toString());
}
return returnValue;
}
}