package com.limegroup.gnutella.licenses;
import org.apache.commons.httpclient.URI;
import org.apache.commons.httpclient.URIException;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.logging.Log;
import com.limegroup.gnutella.URN;
import com.limegroup.gnutella.metadata.WeedInfo;
import com.limegroup.gnutella.metadata.WRMXML;
/**
* A factory for constructing Licenses based on licenses.
*/
public final class LicenseFactory {
private static final Log LOG = LogFactory.getLog(LicenseFactory.class);
public static final String WEED_NAME = "Weed License";
public static final String CC_NAME = "Creative Commons License";
public static final String UNKNOWN_NAME = "Unknown License";
private LicenseFactory() {}
/**
* Checks if the specified license-URI is valid for the given URN
* without doing any expensive lookups.
*
* The URI must have been retrieved via getLicenseURI.
*
*/
public static boolean isVerifiedAndValid(URN urn, String licenseString) {
URI uri = getLicenseURI(licenseString);
return uri != null && LicenseCache.instance().isVerifiedAndValid(urn, uri);
}
/**
* Gets the name associated with this license string.
*/
public static String getLicenseName(String licenseString) {
if(isCCLicense(licenseString))
return CC_NAME;
else if(isWeedLicense(licenseString))
return WEED_NAME;
else if(isUnknownLicense(licenseString))
return UNKNOWN_NAME;
else
return null;
}
/**
* Returns a License for the given license string, if one
* can be constructed. If no License exists to validate
* the license, returns null.
*/
public static License create(String licenseString) {
if(licenseString == null)
return null;
if(LOG.isTraceEnabled())
LOG.trace("Attempting to create license from: " + licenseString);
License license = null;
URI uri = getLicenseURI(licenseString);
// Try to get a cached version, first.
if(uri != null)
license = LicenseCache.instance().getLicense(licenseString, uri);
// If the cached version didn't exist, try to make one.
if(license == null) {
if(isCCLicense(licenseString)) {
if(uri != null)
license = new CCLicense(licenseString, uri);
else
license = new BadCCLicense(licenseString);
} else if(isWeedLicense(licenseString) && uri != null) {
license = new WeedLicense(uri);
} else if(isUnknownLicense(licenseString)) {
license = new UnknownLicense();
}
}
// If we managed to get one, and it's a NamedLicense, try and set its name.
if(license != null && license instanceof NamedLicense)
((NamedLicense)license).setLicenseName(getLicenseName(licenseString));
return license;
}
/** Determines if the given string can be a CC license. */
private static boolean isCCLicense(String s) {
return s.indexOf(CCConstants.URL_INDICATOR) != -1;
}
/** Determines if the given string can be a Weed license. */
private static boolean isWeedLicense(String s) {
return s.startsWith(WeedInfo.LAINFO);
}
/** Determines if the given string can be an Unknown license. */
private static boolean isUnknownLicense(String s) {
return s.startsWith(WRMXML.PROTECTED);
}
/**
* Persists the cache.
*/
public static void persistCache() {
LicenseCache.instance().persistCache();
}
/**
* Determines the URI to verify this license at from the license string.
*/
static URI getLicenseURI(String license) {
if(license == null)
return null;
// Look for CC first.
URI uri = getCCLicenseURI(license);
// Then Weed.
if(uri == null)
uri = getWeedLicenseURI(license);
// ADD MORE LICENSES IN THE FORM OF
// if( uri == null)
// uri = getXXXLicenseURI(license)
// AS WE UNDERSTAND MORE...
return uri;
}
/** Gets a CC license URI from the given license string. */
private static URI getCCLicenseURI(String license) {
// find where the URL should begin.
int verifyAt = license.indexOf(CCConstants.URL_INDICATOR);
if(verifyAt == -1)
return null;
int urlStart = verifyAt + CCConstants.URL_INDICATOR.length();
if(urlStart >= license.length())
return null;
String url = license.substring(urlStart).trim();
URI uri = null;
try {
uri = new URI(url.toCharArray());
// Make sure the scheme is HTTP.
String scheme = uri.getScheme();
if(scheme == null || !scheme.equalsIgnoreCase("http"))
throw new URIException("Invalid scheme: " + scheme);
// Make sure the scheme has some authority.
String authority = uri.getAuthority();
if(authority == null || authority.equals("") || authority.indexOf(' ') != -1)
throw new URIException("Invalid authority: " + authority);
} catch(URIException e) {
uri = null;
LOG.error("Unable to create URI", e);
}
return uri;
}
/** Gets a Weed license URI from the given license string. */
private static URI getWeedLicenseURI(String license) {
int lainfo = license.indexOf(WeedInfo.LAINFO);
if(lainfo == -1)
return null;
int cidx = license.indexOf(WeedInfo.CID);
int vidx = license.indexOf(WeedInfo.VID);
// If no cid or vid, exit.
if(cidx == -1 || vidx == -1) {
LOG.debug("No cid or vid, bailing.");
return null;
}
cidx += WeedInfo.CID.length();;
vidx += WeedInfo.VID.length();;
int cend = license.indexOf(" ", cidx);
int vend = license.indexOf(" ", vidx);
// If there's no ending space for BOTH, exit.
// (it's okay if one is at the end, but both can't be)
if(cend == -1 && vend == -1) {
LOG.debug("No endings for both cid & vid, bailing");
return null;
}
if(cend == -1)
cend = license.length();
if(vend == -1)
vend = license.length();
// If the cid or vid are empty, exit.
String cid = license.substring(cidx, cend).trim();
String vid = license.substring(vidx, vend).trim();
if(cid.length() == 0 || vid.length() == 0) {
LOG.debug("cid or vid is empty, bailing");
return null;
}
if(cid.startsWith(WeedInfo.VID.trim()) || vid.startsWith(WeedInfo.CID.trim())) {
LOG.debug("cid starts with vid, or vice versa, bailing.");
return null;
}
return WeedLicense.buildURI(cid, vid);
}
}