mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-06-09 17:45:10 +00:00
svn merge svn://www.alfresco.org:3691/alfresco/BRANCHES/V1.3@2976 svn://www.alfresco.org:3691/alfresco/BRANCHES/V1.3@3004 . git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@3335 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
494 lines
18 KiB
Java
494 lines
18 KiB
Java
/*
|
|
* Copyright (C) 2005 Alfresco, Inc.
|
|
*
|
|
* Licensed under the Alfresco Network License. You may obtain a
|
|
* copy of the License at
|
|
*
|
|
* http://www.alfrescosoftware.com/legal/
|
|
*
|
|
* Please view the license relevant to your network subscription.
|
|
*
|
|
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
|
|
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
|
|
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
|
|
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
|
|
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
|
|
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
|
|
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
|
|
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
|
|
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
|
|
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
|
|
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
|
|
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
|
|
*/
|
|
package org.alfresco.license;
|
|
|
|
import java.io.ByteArrayInputStream;
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.Serializable;
|
|
import java.util.Collection;
|
|
import java.util.Date;
|
|
import java.util.List;
|
|
import java.util.Properties;
|
|
|
|
import org.alfresco.model.ContentModel;
|
|
import org.alfresco.repo.admin.patch.PatchDaoService;
|
|
import org.alfresco.repo.content.MimetypeMap;
|
|
import org.alfresco.repo.domain.AppliedPatch;
|
|
import org.alfresco.repo.importer.ImporterBootstrap;
|
|
import org.alfresco.repo.transaction.TransactionComponent;
|
|
import org.alfresco.repo.transaction.TransactionUtil;
|
|
import org.alfresco.repo.transaction.TransactionUtil.TransactionWork;
|
|
import org.alfresco.service.ServiceRegistry;
|
|
import org.alfresco.service.cmr.repository.ContentReader;
|
|
import org.alfresco.service.cmr.repository.ContentService;
|
|
import org.alfresco.service.cmr.repository.ContentWriter;
|
|
import org.alfresco.service.cmr.repository.NodeRef;
|
|
import org.alfresco.service.cmr.repository.NodeService;
|
|
import org.alfresco.service.cmr.repository.StoreRef;
|
|
import org.alfresco.service.cmr.search.SearchService;
|
|
import org.alfresco.service.descriptor.DescriptorService;
|
|
import org.alfresco.service.license.LicenseDescriptor;
|
|
import org.alfresco.service.license.LicenseException;
|
|
import org.alfresco.service.license.LicenseService;
|
|
import org.alfresco.service.namespace.NamespaceService;
|
|
import org.apache.commons.logging.Log;
|
|
import org.apache.commons.logging.LogFactory;
|
|
import org.quartz.Job;
|
|
import org.quartz.JobDetail;
|
|
import org.quartz.JobExecutionContext;
|
|
import org.quartz.JobExecutionException;
|
|
import org.quartz.Scheduler;
|
|
import org.quartz.SchedulerException;
|
|
import org.quartz.SchedulerFactory;
|
|
import org.quartz.Trigger;
|
|
import org.quartz.helpers.TriggerUtils;
|
|
import org.quartz.impl.StdSchedulerFactory;
|
|
import org.springframework.context.ApplicationContext;
|
|
import org.springframework.core.io.Resource;
|
|
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
|
|
|
import de.schlichtherle.license.LicenseContent;
|
|
import de.schlichtherle.license.ftp.LicenseManager;
|
|
import de.schlichtherle.license.ftp.LicenseParam;
|
|
|
|
|
|
/**
|
|
* Alfresco Enterprise Network implementation of License Service
|
|
*
|
|
* @author davidc
|
|
*/
|
|
public class LicenseComponent implements LicenseService
|
|
{
|
|
protected AlfrescoLicenseManager licenseManager;
|
|
private LicenseDescriptor licenseDescriptor = null;
|
|
|
|
// dependencies
|
|
private TransactionComponent transactionComponent;
|
|
private ImporterBootstrap systemBootstrap;
|
|
private SearchService searchService;
|
|
private NamespaceService namespaceService;
|
|
protected NodeService nodeService;
|
|
protected ContentService contentService;
|
|
private Scheduler verifyScheduler = null;
|
|
private boolean failed = false;
|
|
|
|
// logger
|
|
private static final Log logger = LogFactory.getLog(DescriptorService.class);
|
|
private static final Log loggerInternal = LogFactory.getLog(LicenseComponent.class);
|
|
|
|
|
|
/**
|
|
* Construct
|
|
*
|
|
* @param context application context
|
|
*/
|
|
public LicenseComponent(ApplicationContext context)
|
|
{
|
|
transactionComponent = (TransactionComponent)context.getBean("transactionComponent");
|
|
systemBootstrap = (ImporterBootstrap)context.getBean("systemBootstrap");
|
|
nodeService = (NodeService)context.getBean("nodeService");
|
|
searchService = (SearchService)context.getBean("searchService");
|
|
contentService = (ContentService)context.getBean("contentService");
|
|
namespaceService = (NamespaceService)context.getBean(ServiceRegistry.NAMESPACE_SERVICE.getLocalName());
|
|
|
|
// construct license manager
|
|
boolean trialEligibility = getTrialEligibility(context);
|
|
licenseManager = new AlfrescoLicenseManager(new AlfrescoLicenseParam(trialEligibility));
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.service.license.LicenseService#verifyLicense()
|
|
*/
|
|
public void verifyLicense()
|
|
{
|
|
// check to see if there's a license to install
|
|
File licenseFile = getLicenseFile();
|
|
if (licenseFile != null)
|
|
{
|
|
if (logger.isInfoEnabled())
|
|
logger.info("Alfresco license: Installing license file " + licenseFile.getName());
|
|
|
|
try
|
|
{
|
|
LicenseContent licenseContent = licenseManager.install(licenseFile);
|
|
renameLicenseFile(licenseFile);
|
|
licenseDescriptor = new LicenseContentDescriptor(licenseContent);
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
throw new LicenseException("Failed to install license file " + licenseFile.getName(), e);
|
|
}
|
|
}
|
|
|
|
// verify existing license
|
|
if (licenseDescriptor == null)
|
|
{
|
|
verify();
|
|
|
|
// construct scheduler for period license verify
|
|
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
|
|
try
|
|
{
|
|
verifyScheduler = schedulerFactory.getScheduler();
|
|
JobDetail jobDetail = new JobDetail("vlj", Scheduler.DEFAULT_GROUP, VerifyLicenseJob.class);
|
|
jobDetail.getJobDataMap().put("licenseComponent", this);
|
|
Trigger trigger = TriggerUtils.makeHourlyTrigger();
|
|
trigger.setStartTime(new Date(System.currentTimeMillis() + (60L * 1000L))); // one minute from now
|
|
trigger.setName("vlt");
|
|
trigger.setGroup(Scheduler.DEFAULT_GROUP);
|
|
verifyScheduler.scheduleJob(jobDetail, trigger);
|
|
verifyScheduler.start();
|
|
}
|
|
catch(SchedulerException e)
|
|
{
|
|
throw new LicenseException("Failed to initialise License Component");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Verify License
|
|
*/
|
|
protected void verify()
|
|
{
|
|
// note: if a license hasn't been already been installed then install
|
|
// a free trial period
|
|
TransactionWork<LicenseDescriptor> verifyLicense = new TransactionUtil.TransactionWork<LicenseDescriptor>()
|
|
{
|
|
public LicenseDescriptor doWork()
|
|
{
|
|
LicenseDescriptor descriptor = null;
|
|
try
|
|
{
|
|
LicenseContent licenseContent = licenseManager.verify();
|
|
descriptor = new LicenseContentDescriptor(licenseContent);
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
// handle license failure case
|
|
licenseFailed(e);
|
|
}
|
|
return descriptor;
|
|
}
|
|
};
|
|
licenseDescriptor = TransactionUtil.executeInUserTransaction(transactionComponent, verifyLicense);
|
|
}
|
|
|
|
/**
|
|
* Handle case where license is found to be invalid
|
|
*/
|
|
protected void licenseFailed(Exception e)
|
|
throws LicenseException
|
|
{
|
|
if (!failed)
|
|
{
|
|
// Mark transactions as read-only
|
|
transactionComponent.setAllowWrite(false);
|
|
|
|
if (logger.isWarnEnabled())
|
|
{
|
|
logger.warn("Alfresco license: Failed to verify license - Invalid License!");
|
|
logger.warn("Alfresco license: Restricted Alfresco Repository to read-only capability");
|
|
}
|
|
if (loggerInternal.isDebugEnabled())
|
|
{
|
|
loggerInternal.debug("Alfresco license: Failed due to " + e.toString());
|
|
}
|
|
failed = true;
|
|
}
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.service.license.LicenseService#getLicense()
|
|
*/
|
|
public LicenseDescriptor getLicense()
|
|
{
|
|
return licenseDescriptor;
|
|
}
|
|
|
|
/**
|
|
* Determine if a license file is to be installed
|
|
*
|
|
* @return the license file (or null, if one is not to be installed)
|
|
*/
|
|
private File getLicenseFile()
|
|
{
|
|
File licenseFile = null;
|
|
|
|
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
|
|
try
|
|
{
|
|
Resource[] resources = resolver.getResources("classpath*:/alfresco/extension/license/*.lic");
|
|
if (resources.length > 1)
|
|
{
|
|
String resMsg = "";
|
|
for (Resource resource : resources)
|
|
{
|
|
resMsg += "[" + resource.getURL().toExternalForm() + "] ";
|
|
}
|
|
throw new LicenseException("Found more than one license file to install. The licenses found are: " + resMsg);
|
|
}
|
|
if (resources.length > 0)
|
|
{
|
|
licenseFile = resources[0].getFile();
|
|
}
|
|
}
|
|
catch (IOException e)
|
|
{
|
|
// Note: Ignore: license not found
|
|
}
|
|
|
|
return licenseFile;
|
|
}
|
|
|
|
/**
|
|
* Rename installed license file
|
|
*
|
|
* @param licenseFile license file to rename
|
|
*/
|
|
private void renameLicenseFile(File licenseFile)
|
|
{
|
|
File dest = new File(licenseFile.getAbsolutePath() + ".installed");
|
|
boolean success = false;
|
|
try
|
|
{
|
|
success = licenseFile.renameTo(dest);
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
}
|
|
|
|
if (!success)
|
|
{
|
|
if (logger.isWarnEnabled())
|
|
logger.warn("Alfresco license: Failed to rename installed license file " + licenseFile.getName() + " to " + dest.getName());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Determine if eligible for trial license creation
|
|
*
|
|
* @param context application context
|
|
* @return true => trial license may be created
|
|
*/
|
|
private boolean getTrialEligibility(ApplicationContext context)
|
|
{
|
|
// from clean (open)
|
|
// from clean (enterprise)
|
|
// ==> systemBootstrap == true
|
|
|
|
// upgrade from 1.2.1 open to 1.2.1 enterprise
|
|
// ==> patch = true, schema >= 12, versionEdition = open
|
|
|
|
// upgrade from 1.2.1 open to 1.3.0 enterprise
|
|
// ==> patch = true, schema >= 12, versionEdition = open
|
|
|
|
// upgrade from 1.2.1 enterprise to 1.3.0 enterprise
|
|
// ==> patch = true, schema >= 12, versionEdition = license
|
|
|
|
// upgrade from 1.2 open to 1.2.1+ enterprise
|
|
// ==> patch = false, schema < 12, versionEdition = null
|
|
|
|
// upgrade from 1.2 enterprise to 1.2.1+ enterprise
|
|
// ==> patch = false, schema < 12, versionEdition = null
|
|
|
|
|
|
// first determine if the system store has been bootstrapped in this startup sequence
|
|
// if so, a trial license may be created
|
|
boolean trialEligibility = systemBootstrap.hasPerformedBootstrap();
|
|
|
|
if (loggerInternal.isDebugEnabled())
|
|
loggerInternal.debug("Alfresco license: System store bootstrapped: " + trialEligibility);
|
|
|
|
// if not, then this could be a pre-installed repository that has yet to be patched with a license
|
|
if (!trialEligibility)
|
|
{
|
|
NodeRef descriptorRef = getDescriptor();
|
|
if (descriptorRef != null)
|
|
{
|
|
PatchDaoService patchDao = (PatchDaoService)context.getBean("patchDaoComponent");
|
|
AppliedPatch patch = patchDao.getAppliedPatch("patch.descriptorUpdate");
|
|
|
|
// versionEdition = open
|
|
// patch = true, schema >= 12
|
|
|
|
// versionEdition = null
|
|
// patch = false, schema < 12
|
|
|
|
// versionEdition = license
|
|
// not eligible
|
|
|
|
int schema = (Integer)nodeService.getProperty(descriptorRef, ContentModel.PROP_SYS_VERSION_SCHEMA);
|
|
Serializable value = nodeService.getProperty(descriptorRef, ContentModel.PROP_SYS_VERSION_EDITION);
|
|
|
|
if (loggerInternal.isDebugEnabled())
|
|
{
|
|
loggerInternal.debug("Alfresco license: patch applied: " + (patch != null));
|
|
loggerInternal.debug("Alfresco license: schema: " + schema);
|
|
loggerInternal.debug("Alfresco license: edition: " + value);
|
|
}
|
|
|
|
if (value == null)
|
|
{
|
|
trialEligibility = (patch == null) && schema < 12;
|
|
}
|
|
else if (value instanceof Collection)
|
|
{
|
|
Collection editions = (Collection)value;
|
|
Object editionsValue = (editions.size() > 0) ? editions.iterator().next() : null;
|
|
String edition = (editionsValue instanceof String) ? (String)editionsValue : "";
|
|
trialEligibility = (patch != null) && schema >=12 && edition.equals("Community Network");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (loggerInternal.isDebugEnabled())
|
|
loggerInternal.debug("Alfresco license: trial eligibility: " + trialEligibility);
|
|
|
|
return trialEligibility;
|
|
}
|
|
|
|
/**
|
|
* Get System Store Descriptor
|
|
*
|
|
* @return node reference of system store descriptor
|
|
*/
|
|
protected NodeRef getDescriptor()
|
|
{
|
|
StoreRef storeRef = systemBootstrap.getStoreRef();
|
|
List<NodeRef> nodeRefs = null;
|
|
|
|
if (nodeService.exists(storeRef))
|
|
{
|
|
Properties systemProperties = systemBootstrap.getConfiguration();
|
|
String path = systemProperties.getProperty("system.descriptor.current.childname");
|
|
String searchPath = "/" + path;
|
|
NodeRef rootNodeRef = nodeService.getRootNode(storeRef);
|
|
nodeRefs = searchService.selectNodes(rootNodeRef, searchPath, null, namespaceService, false);
|
|
}
|
|
|
|
return (nodeRefs == null || nodeRefs.size() == 0) ? null : nodeRefs.get(0);
|
|
}
|
|
|
|
|
|
/**
|
|
* Job for period license verification
|
|
*
|
|
* @author davidc
|
|
*/
|
|
public static class VerifyLicenseJob implements Job
|
|
{
|
|
public void execute(JobExecutionContext context) throws JobExecutionException
|
|
{
|
|
LicenseComponent license = (LicenseComponent)context.getJobDetail().getJobDataMap().get("licenseComponent");
|
|
license.verify();
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Alfresco implementation of License Manager
|
|
*
|
|
* Note: Stores verified license files in Alfresco Repository
|
|
*
|
|
* @author davidc
|
|
*/
|
|
public class AlfrescoLicenseManager extends LicenseManager
|
|
{
|
|
/**
|
|
* Construct
|
|
*
|
|
* @param context application context
|
|
* @param param license parameters
|
|
*/
|
|
public AlfrescoLicenseManager(LicenseParam param)
|
|
{
|
|
super(param);
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see de.schlichtherle.license.LicenseManager#getLicenseKey()
|
|
*/
|
|
protected byte[] getLicenseKey()
|
|
{
|
|
byte[] key = null;
|
|
|
|
try
|
|
{
|
|
NodeRef descriptorRef = getDescriptor();
|
|
if (descriptorRef == null)
|
|
{
|
|
throw new LicenseException("Failed to find system descriptor");
|
|
}
|
|
ContentReader reader = contentService.getReader(descriptorRef, ContentModel.PROP_SYS_VERSION_EDITION);
|
|
if (reader != null && reader.exists())
|
|
{
|
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
|
reader.getContent(os);
|
|
key = os.toByteArray();
|
|
}
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
throw new LicenseException("Failed to load license", e);
|
|
}
|
|
return key;
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see de.schlichtherle.license.LicenseManager#setLicenseKey(byte[])
|
|
*/
|
|
protected synchronized void setLicenseKey(final byte[] key)
|
|
{
|
|
try
|
|
{
|
|
NodeRef descriptorRef = getDescriptor();
|
|
if (descriptorRef == null)
|
|
{
|
|
throw new LicenseException("Failed to find system descriptor");
|
|
}
|
|
if (key == null)
|
|
{
|
|
nodeService.setProperty(descriptorRef, ContentModel.PROP_SYS_VERSION_EDITION, null);
|
|
}
|
|
else
|
|
{
|
|
ContentWriter writer = contentService.getWriter(descriptorRef, ContentModel.PROP_SYS_VERSION_EDITION, true);
|
|
InputStream is = new ByteArrayInputStream(key);
|
|
writer.setMimetype(MimetypeMap.MIMETYPE_BINARY);
|
|
writer.putContent(is);
|
|
}
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
throw new LicenseException("Failed to save license", e);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|