WrapperClassNamingConvention.java
/**
* 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.cxf.jaxws.spi;
import java.util.Locale;
import java.util.regex.Pattern;
import org.apache.cxf.common.util.PackageUtils;
/**
* Provides names for storing generated wrapper classes.
*
* @since 4.1.1
*/
public interface WrapperClassNamingConvention {
/**
* Returns a package name unique for the given {@code sei} and {@code anonymous}
* parameters suitable for storing generated wrapper classes.
*
* @param sei the service endpoint interface for which the package name should be created
* @param anonymous whether the generated wrapper types are anonymous
* @return a valid Java package name
*/
String getWrapperClassPackageName(Class<?> sei, boolean anonymous);
/**
* Default naming scheme since CXF 4.2.0.
* <p>
* The package name returned by {@link #getWrapperClassPackageName(Class, boolean)} are unique
* per given {@code sei}.
* <p>
* Examples:
* <table>
* <tr>
* <th>SEI</th><th>anonymous</th>
* <th>{@code getWrapperClassPackageName()} return value</th>
* </tr>
* <tr>
* <td>{@code org.example.Service}</td>
* <td>{@code false}</td>
* <td>{@code org.example.jaxws_asm.service}</td>
* </tr>
* <tr>
* <td>{@code org.example.OuterClass$Service}</td>
* <td>{@code false}</td>
* <td>{@code org.example.jaxws_asm.outerclass_service}</td>
* </tr>
* <tr>
* <td>{@code org.example.Service}</td>
* <td>{@code true}</td>
* <td>{@code org.example.jaxws_asm_an.service}</td>
* </tr>
* </table>
*
* @since 4.1.1
*/
class DefaultWrapperClassNamingConvention implements WrapperClassNamingConvention {
public static final String DEFAULT_PACKAGE_NAME = "defaultnamespace";
private static final Pattern JAVA_PACKAGE_NAME_SANITIZER_PATTERN = Pattern.compile("[^a-zA-Z0-9_]");
@Override
public String getWrapperClassPackageName(Class<?> sei, boolean anonymous) {
final String className = sei.getName();
final int start = className.startsWith("[L") ? 2 : 0;
final int end = className.lastIndexOf('.');
final String pkg;
final String cl;
if (end >= 0) {
pkg = className.substring(start, end);
cl = className.substring(end + 1);
} else {
pkg = DefaultWrapperClassNamingConvention.DEFAULT_PACKAGE_NAME;
cl = className;
}
return pkg
+ (anonymous ? ".jaxws_asm_an." : ".jaxws_asm.")
+ JAVA_PACKAGE_NAME_SANITIZER_PATTERN.matcher(cl).replaceAll("_").toLowerCase(Locale.ROOT);
}
}
/**
* An implementation restoring the behavior of CXF before version 4.2.0.
* <p>
* Unlike with {@link DefaultWrapperClassNamingConvention}, this implementation's
* {@link #getWrapperClassPackageName(Class, boolean)} takes only package name
* of the given {@code sei} into account.
* Therefore naming clashes may occur if two SEIs are in the same package
* and both of them have a method with the same name but possibly different signature.
* <p>
* Examples:
* <table>
* <tr>
* <th>SEI</th>
* <th>anonymous</th>
* <th>{@code getWrapperClassPackageName()} return value</th>
* </tr>
* <tr>
* <td>{@code org.example.Service}</td>
* <td>{@code false}</td>
* <td>{@code org.example.jaxws_asm}</td>
* </tr>
* <tr>
* <td>{@code org.example.OuterClass$Service}</td>
* <td>{@code false}</td>
* <td>{@code org.example.jaxws_asm}</td>
* </tr>
* <tr>
* <td>{@code org.example.Service}</td>
* <td>{@code true}</td>
* <td>{@code org.example.jaxws_asm_an}</td>
* </tr>
* </table>
*
* @since 4.1.1
*/
class LegacyWrapperClassNamingConvention implements WrapperClassNamingConvention {
@Override
public String getWrapperClassPackageName(Class<?> sei, boolean anonymous) {
return getPackageName(sei) + ".jaxws_asm" + (anonymous ? "_an" : "");
}
private String getPackageName(Class<?> sei) {
String pkg = PackageUtils.getPackageName(sei);
return pkg.length() == 0 ? DefaultWrapperClassNamingConvention.DEFAULT_PACKAGE_NAME : pkg;
}
}
}