/* * JBoss, Home of Professional Open Source * * Distributable under LGPL license. See terms of license at gnu.org. */ package org.jboss.seam.init; import java.net.URI; import org.jboss.seam.log.LogProvider; import org.jboss.seam.log.Logging; /** * <p>Converts an <a href="http://www.w3.org/TR/xml-names/">XML namespace</a> to a Java package name.</p> * * @author <a href="mailto:eric DOT jung AT yahoo DOT com">Eric H. Jung</a> */ public class NamespacePackageResolver { private static final String JAVA_SCHEME = "java"; @SuppressWarnings("unused") private static final LogProvider log = Logging.getLogProvider(NamespacePackageResolver.class); /** * <p>Converts an XML namespace, <code>ns</code>, to a Stringified package name * * @param ns the xml namespace to convert * * @returns a namespace descriptor */ public String resolve(final String ns) { try { return parseURI(new URI(ns)); } catch (Exception e) { // the exact exception doesn't matter here. The caller // can log if needed return null; } } private String parseURI(URI uri) { if (!uri.isAbsolute()) { throw new IllegalArgumentException(uri + " is not an absolute URI"); } return uri.isOpaque() ? parseOpaqueURI(uri) : parseHierarchicalURI(uri); } /** * java:package * seam:component * seam:package:prefix */ private String parseOpaqueURI(URI uri) { if (uri.getScheme().equalsIgnoreCase(JAVA_SCHEME)) { return uri.getSchemeSpecificPart(); } throw new IllegalArgumentException("Unrecognized scheme in " + uri); } private String parseHierarchicalURI(URI uri) { String scheme = uri.getScheme().toLowerCase(); if (!scheme.equals("http") && !scheme.equals("https")) { throw new IllegalArgumentException("Hierarchical URLs must use http or https scheme " + uri); } StringBuffer buf = new StringBuffer(); appendToPackageName(buf, hostnameToPackage(uri.getHost())); appendToPackageName(buf, pathToPackage(uri.getPath())); return buf.toString(); } /** * Convert path elements to package names in forward order */ private String pathToPackage(String path) { StringBuffer buf = new StringBuffer(); if (path != null) { String[] pathElements = path.split("/"); for (int i = 1, len = pathElements.length; i < len; i++) { appendToPackageName(buf, pathElements[i]); } } return buf.toString(); } private String hostnameToPackage(String hostname) { StringBuffer result = new StringBuffer(); String[] subdomains = hostname.split("\\."); //Iterate through the subdomains in reverse converting each to a package name. for (int i = subdomains.length - 1; i >= 0; i--) { String subdomain = subdomains[i]; if (i > 0 || !subdomain.equalsIgnoreCase("www")) { appendToPackageName(result, subdomain); } } return result.toString(); } private void appendToPackageName(StringBuffer buf, String subdomain) { if (subdomain.length()>0) { subdomain = makeSafeForJava(subdomain); if (buf.length() > 0) { buf.append('.'); } buf.append(subdomain); } } /** * Converts characters in <code>subdomain</code> which aren't java-friendly * into java-friendly equivalents. Right now, we only support the conversion * of hyphens ("-") to underscores ("_"). We could do other things like toLowerCase(), * but there are instances of upper-case package names in widespread use even by the * likes of IBM (e.g., <a href="http://publib.boulder.ibm.com/infocenter/db2luw/v8/index.jsp?topic=/com.ibm.db2.udb.dc.doc/dc/r_jdbcdrivers.htm"> * COM.ibm.db2 classnames</a>). * * @param subdomain * @return */ private String makeSafeForJava(String subdomain) { return subdomain.replace("-", "_"); } }