canLock(contentlet, user);
}
contentlet.setModUser(user.getUserId());
// start up workflow
WorkflowAPI wapi = APILocator.getWorkflowAPI();
WorkflowProcessor workflow=null;
if(contentlet.getMap().get("__disable_workflow__")==null) {
workflow = wapi.fireWorkflowPreCheckin(contentlet,user);
}
workingContentlet = contentlet;
if(createNewVersion)
workingContentlet = findWorkingContentlet(contentlet);
String workingContentletInode = (workingContentlet==null) ? "" : workingContentlet.getInode();
boolean priority = contentlet.isLowIndexPriority();
boolean isNewContent = false;
if(!InodeUtils.isSet(workingContentletInode)){
isNewContent = true;
}
if (contentlet.getLanguageId() == 0) {
Language defaultLanguage = lanAPI.getDefaultLanguage();
contentlet.setLanguageId(defaultLanguage.getId());
}
contentlet.setModUser(user != null ? user.getUserId() : "");
if (contentlet.getOwner() == null || contentlet.getOwner().length() < 1) {
contentlet.setOwner(user.getUserId());
}
// check contentlet Host
User sysuser = APILocator.getUserAPI().getSystemUser();
if (!UtilMethods.isSet(contentlet.getHost())) {
contentlet.setHost(APILocator.getHostAPI().findSystemHost(sysuser, true).getIdentifier());
}
if (!UtilMethods.isSet(contentlet.getFolder())) {
contentlet.setFolder(FolderAPI.SYSTEM_FOLDER);
}
Contentlet contentletRaw=contentlet;
if ( contentlet.getMap().get( "_use_mod_date" ) != null ) {
/*
When a content is sent using the remote push publishing we want to respect the modification
dates the content already had.
*/
contentlet.setModDate( (Date) contentlet.getMap().get( "_use_mod_date" ) );
} else {
contentlet.setModDate( new Date() );
}
// Keep the 5 properties BEFORE store the contentlet on DB.
contentPushPublishDate = contentlet.getStringProperty("wfPublishDate");
contentPushPublishTime = contentlet.getStringProperty("wfPublishTime");
contentPushExpireDate = contentlet.getStringProperty("wfExpireDate");
contentPushExpireTime = contentlet.getStringProperty("wfExpireTime");
String contentPushNeverExpire = contentlet.getStringProperty("wfNeverExpire");
String contentWhereToSend = contentlet.getStringProperty("whereToSend");
String forcePush = contentlet.getStringProperty("forcePush");
if(saveWithExistingID)
contentlet = conFac.save(contentlet, existingInode);
else
contentlet = conFac.save(contentlet);
if (!InodeUtils.isSet(contentlet.getIdentifier())) {
Treeable parent = null;
if(UtilMethods.isSet(contentletRaw.getFolder()) && !contentletRaw.getFolder().equals(FolderAPI.SYSTEM_FOLDER)){
parent = APILocator.getFolderAPI().find(contentletRaw.getFolder(), sysuser, false);
}else{
parent = APILocator.getHostAPI().find(contentlet.getHost(), sysuser, false);
}
Identifier ident;
final Contentlet contPar=contentlet.getStructure().getStructureType()==Structure.STRUCTURE_TYPE_FILEASSET?contentletRaw:contentlet;
if(existingIdentifier!=null)
ident = APILocator.getIdentifierAPI().createNew(contPar, parent, existingIdentifier);
else
ident = APILocator.getIdentifierAPI().createNew(contPar, parent);
contentlet.setIdentifier(ident.getId());
contentlet = conFac.save(contentlet);
} else {
Identifier ident = APILocator.getIdentifierAPI().find(contentlet);
String oldURI=ident.getURI();
// make sure the identifier is removed from cache
// because changes here may affect URI then IdentifierCache
// can't remove it
CacheLocator.getIdentifierCache().removeFromCacheByVersionable(contentlet);
ident.setHostId(contentlet.getHost());
if(contentlet.getStructure().getStructureType()==Structure.STRUCTURE_TYPE_FILEASSET){
try {
ident.setAssetName(contentletRaw.getBinary(FileAssetAPI.BINARY_FIELD).getName());
} catch (IOException e) {
// TODO
}
}
if(UtilMethods.isSet(contentletRaw.getFolder()) && !contentletRaw.getFolder().equals(FolderAPI.SYSTEM_FOLDER)){
Folder folder = APILocator.getFolderAPI().find(contentletRaw.getFolder(), sysuser, false);
Identifier folderIdent = APILocator.getIdentifierAPI().find(folder);
ident.setParentPath(folderIdent.getPath());
}
else {
ident.setParentPath("/");
}
ident=APILocator.getIdentifierAPI().save(ident);
changedURI = ! oldURI.equals(ident.getURI());
}
APILocator.getVersionableAPI().setWorking(contentlet);
boolean structureHasAHostField = hasAHostField(contentlet.getStructureInode());
List<Field> fields = FieldsCache.getFieldsByStructureInode(contentlet.getStructureInode());
for (Field field : fields) {
if (field.getFieldType().equals(Field.FieldType.TAG.toString())) {
String value= null;
if(contentlet.getStringProperty(field.getVelocityVarName()) != null)
value=contentlet.getStringProperty(field.getVelocityVarName()).trim();
if(UtilMethods.isSet(value)) {
String hostId = Host.SYSTEM_HOST;
if(structureHasAHostField){
Host host = null;
try{
host = APILocator.getHostAPI().find(contentlet.getHost(), user, true);
}catch(Exception e){
Logger.error(this, "Unable to get contentlet host");
Logger.debug(this, "Unable to get contentlet host", e);
}
if(host.getIdentifier().equals(Host.SYSTEM_HOST))
hostId = Host.SYSTEM_HOST;
else
hostId = host.getIdentifier();
}
List<Tag> list=tagAPI.getTagsInText(value, "", hostId);
for(Tag tag : list)
tagAPI.addTagInode(tag.getTagName(), contentlet.getInode(), hostId);
}
}
}
if (workingContentlet == null) {
workingContentlet = contentlet;
}
// DOTCMS-4732
// if(isNewContent && !hasAHostFieldSet(contentlet.getStructureInode(),contentlet)){
// List<Permission> stPers = perAPI.getPermissions(contentlet.getStructure());
// if(stPers != null && stPers.size()>0){
// if(stPers.get(0).isIndividualPermission()){
// perAPI.copyPermissions(contentlet.getStructure(), contentlet);
// }
// }
// }else{
// perAPI.resetPermissionReferences(contentlet);
// }
if (createNewVersion || (!createNewVersion && (contentRelationships != null || cats != null))) {
moveContentDependencies(workingContentlet, contentlet, contentRelationships, cats, permissions, user, respectFrontendRoles);
}
// Refreshing permissions
if (hasAHostField(contentlet.getStructureInode()) && !isNewContent) {
perAPI.resetPermissionReferences(contentlet);
}
// Publish once if needed and reindex once if needed. The publish
// method reindexes.
contentlet.setLowIndexPriority(priority);
// http://jira.dotmarketing.net/browse/DOTCMS-1073
// storing binary files in file system.
Logger.debug(this, "ContentletAPIImpl : storing binary files in file system.");
// Binary Files
String newInode = contentlet.getInode();
String oldInode = workingContentlet.getInode();
java.io.File newDir = new java.io.File(APILocator.getFileAPI().getRealAssetPath() + java.io.File.separator
+ newInode.charAt(0)
+ java.io.File.separator
+ newInode.charAt(1) + java.io.File.separator + newInode);
newDir.mkdirs();
java.io.File oldDir = null;
if(UtilMethods.isSet(oldInode)) {
oldDir = new java.io.File(APILocator.getFileAPI().getRealAssetPath()
+ java.io.File.separator + oldInode.charAt(0)
+ java.io.File.separator + oldInode.charAt(1)
+ java.io.File.separator + oldInode);
}
java.io.File tmpDir = null;
if(UtilMethods.isSet(oldInode)) {
tmpDir = new java.io.File(APILocator.getFileAPI().getRealAssetPathTmpBinary()
+ java.io.File.separator + oldInode.charAt(0)
+ java.io.File.separator + oldInode.charAt(1)
+ java.io.File.separator + oldInode);
}
// loop over the new field values
// if we have a new temp file or a deleted file
// do it to the new inode directory
List<Field> structFields = FieldsCache.getFieldsByStructureInode(contentlet.getStructureInode());
for (Field field : structFields) {
if (field.getFieldContentlet().startsWith("binary")) {
try {
String velocityVarNm = field.getVelocityVarName();
java.io.File incomingFile = contentletRaw.getBinary(velocityVarNm);
java.io.File binaryFieldFolder = new java.io.File(newDir.getAbsolutePath() + java.io.File.separator + velocityVarNm);
java.io.File metadata=null;
if(contentlet.getStructure().getStructureType()==Structure.STRUCTURE_TYPE_FILEASSET) {
metadata=APILocator.getFileAssetAPI().getContentMetadataFile(contentlet.getInode());
}
// if the user has removed this file via the ui
if (incomingFile == null || incomingFile.getAbsolutePath().contains("-removed-")){
FileUtil.deltree(binaryFieldFolder);
contentlet.setBinary(velocityVarNm, null);
if(metadata!=null && metadata.exists())
metadata.delete();
continue;
}
// if we have an incoming file
else if (incomingFile.exists() ){
String oldFileName = incomingFile.getName();
String newFileName = (UtilMethods.isSet(contentlet.getStringProperty("fileName")) && contentlet.getStructure().getStructureType() == Structure.STRUCTURE_TYPE_FILEASSET) ? contentlet.getStringProperty("fileName"): oldFileName;
java.io.File oldFile = null;
if(UtilMethods.isSet(oldInode)) {
//get old file
oldFile = new java.io.File(oldDir.getAbsolutePath() + java.io.File.separator + velocityVarNm + java.io.File.separator + oldFileName);
// do we have an inline edited file, if so use that
java.io.File editedFile = new java.io.File(tmpDir.getAbsolutePath() + java.io.File.separator + velocityVarNm + java.io.File.separator + WebKeys.TEMP_FILE_PREFIX + oldFileName);
if(editedFile.exists()){
incomingFile = editedFile;
}
}
java.io.File newFile = new java.io.File(newDir.getAbsolutePath() + java.io.File.separator + velocityVarNm + java.io.File.separator + newFileName);
binaryFieldFolder.mkdirs();
// we move files that have been newly uploaded or edited
if(oldFile==null || !oldFile.equals(incomingFile)){
//FileUtil.deltree(binaryFieldFolder);
FileUtil.move(incomingFile, newFile);
// delete old content metadata if exists
if(metadata!=null && metadata.exists())
metadata.delete();
// what happens is we never clean up the temp directory
// answer: this happends --> https://github.com/dotCMS/dotCMS/issues/1071
// there is a quarz job to clean that
/*java.io.File delMe = new java.io.File(incomingFile.getParentFile().getParentFile(), oldFileName);
if(delMe.exists() && delMe.getAbsolutePath().contains(
APILocator.getFileAPI().getRealAssetPathTmpBinary()
+ java.io.File.separator + user.getUserId()
+ java.io.File.separator ) ){
delMe.delete();
delMe = incomingFile.getParentFile().getParentFile();
FileUtil.deltree(delMe);
}*/
}
else if (oldFile.exists()) {
// otherwise, we copy the files as hardlinks
FileUtil.copyFile(oldFile, newFile);
// try to get the content metadata from the old version
if(metadata!=null) {
java.io.File oldMeta=APILocator.getFileAssetAPI().getContentMetadataFile(oldInode);
if(oldMeta.exists()) {
if(metadata.exists()) // unlikely to happend. deleting just in case
metadata.delete();
metadata.getParentFile().mkdirs();
FileUtil.copyFile(oldMeta, metadata);
}
}
}
contentlet.setBinary(velocityVarNm, newFile);
}
} catch (FileNotFoundException e) {
throw new DotContentletValidationException("Error occurred while processing the file:" + e.getMessage(),e);
} catch (IOException e) {
throw new DotContentletValidationException("Error occurred while processing the file:" + e.getMessage(),e);
}
}
}
// lets update identifier's syspubdate & sysexpiredate
if ((contentlet != null) && InodeUtils.isSet(contentlet.getIdentifier())) {
Structure st=contentlet.getStructure();
if(UtilMethods.isSet(st.getPublishDateVar()) || UtilMethods.isSet(st.getPublishDateVar())) {
Identifier ident=APILocator.getIdentifierAPI().find(contentlet);
boolean save=false;
if(UtilMethods.isSet(st.getPublishDateVar())) {
Date pdate=contentletRaw.getDateProperty(st.getPublishDateVar());
contentlet.setDateProperty(st.getPublishDateVar(), pdate);
if((ident.getSysPublishDate()==null && pdate!=null) || // was null and now we have a value
(ident.getSysPublishDate()!=null && //wasn't null and now is null or different
(pdate==null || !pdate.equals(ident.getSysPublishDate())))) {
ident.setSysPublishDate(pdate);
save=true;
}
}
if(UtilMethods.isSet(st.getExpireDateVar())) {
Date edate=contentletRaw.getDateProperty(st.getExpireDateVar());
contentlet.setDateProperty(st.getExpireDateVar(), edate);
if((ident.getSysExpireDate()==null && edate!=null) || // was null and now we have a value
(ident.getSysExpireDate()!=null && //wasn't null and now is null or different
(edate==null || !edate.equals(ident.getSysExpireDate())))) {
ident.setSysExpireDate(edate);
save=true;
}
}
if (!contentlet.isLive() && UtilMethods.isSet( st.getExpireDateVar() ) ) {//Verify if the structure have a Expire Date Field set
if(UtilMethods.isSet(ident.getSysExpireDate()) && ident.getSysExpireDate().before( new Date())) {
throw new DotContentletValidationException( "message.contentlet.expired" );
}
}
if(save) {
// publish/expire dates changed
APILocator.getIdentifierAPI().save(ident);
// we take all inodes associated with that identifier
// remove them from cache and then reindex them
HibernateUtil hu=new HibernateUtil(ContentletVersionInfo.class);
hu.setQuery("from "+ContentletVersionInfo.class.getCanonicalName()+" where identifier=?");
hu.setParam(ident.getId());
List<ContentletVersionInfo> list=hu.list();
List<String> inodes=new ArrayList<String>();
for(ContentletVersionInfo cvi : list) {
inodes.add(cvi.getWorkingInode());
if(UtilMethods.isSet(cvi.getLiveInode()) && !cvi.getWorkingInode().equals(cvi.getLiveInode()))
inodes.add(cvi.getLiveInode());
}
for(String inode : inodes) {
CacheLocator.getContentletCache().remove(inode);
Contentlet ct=APILocator.getContentletAPI().find(inode, sysuser, false);
APILocator.getContentletIndexAPI().addContentToIndex(ct,false);
}
}
}
}
Structure hostStructure = StructureCache.getStructureByVelocityVarName("Host");
if ((contentlet != null) && InodeUtils.isSet(contentlet.getIdentifier()) && contentlet.getStructureInode().equals(hostStructure.getInode())) {
HostAPI hostAPI = APILocator.getHostAPI();
hostAPI.updateCache(new Host(contentlet));
ContentletCache cc = CacheLocator.getContentletCache();
Identifier ident=APILocator.getIdentifierAPI().find(contentlet);
List<Contentlet> contentlets = findAllVersions(ident, sysuser, respectFrontendRoles);
for (Contentlet c : contentlets) {
Host h = new Host(c);
cc.remove(h.getHostname());
cc.remove(h.getIdentifier());
}
hostAPI.updateVirtualLinks(new Host(workingContentlet), new Host(contentlet));//DOTCMS-5025
hostAPI.updateMenuLinks(new Host(workingContentlet), new Host(contentlet));
//update tag references
String oldTagStorageId = "SYSTEM_HOST";
if(workingContentlet.getMap().get("tagStorage")!=null) {
oldTagStorageId = workingContentlet.getMap().get("tagStorage").toString();
}
String newTagStorageId = "SYSTEM_HOST";
if(contentlet.getMap().get("tagStorage")!=null) {
newTagStorageId = contentlet.getMap().get("tagStorage").toString();
}
tagAPI.updateTagReferences(contentlet.getIdentifier(), oldTagStorageId, newTagStorageId);
}
if(contentlet.getStructure().getStructureType()==Structure.STRUCTURE_TYPE_FILEASSET){
Identifier contIdent = APILocator.getIdentifierAPI().find(contentlet);
//Parse file META-DATA
java.io.File binFile = getBinaryFile(contentlet.getInode(), FileAssetAPI.BINARY_FIELD, user);
if(binFile!=null){
contentlet.setProperty(FileAssetAPI.FILE_NAME_FIELD, binFile.getName());
if(!UtilMethods.isSet(contentlet.getStringProperty(FileAssetAPI.DESCRIPTION))){
String desc = UtilMethods.getFileName(binFile.getName());
contentlet.setProperty(FileAssetAPI.DESCRIPTION, desc);
}
Map<String, String> metaMap = APILocator.getFileAssetAPI().getMetaDataMap(contentlet, binFile);
if(metaMap!=null) {
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
contentlet.setProperty(FileAssetAPI.META_DATA_FIELD, gson.toJson(metaMap));
contentlet = conFac.save(contentlet);
if(!isNewContent){
LiveCache.removeAssetFromCache(contentlet);
LiveCache.addToLiveAssetToCache(contentlet);
WorkingCache.removeAssetFromCache(contentlet);
WorkingCache.addToWorkingAssetToCache(contentlet);
Host host = APILocator.getHostAPI().find(contIdent.getHostId(), user, respectFrontendRoles);
Folder folder = APILocator.getFolderAPI().findFolderByPath(contIdent.getParentPath(), host , user, respectFrontendRoles);
if(RefreshMenus.shouldRefreshMenus(APILocator.getFileAssetAPI().fromContentlet(workingContentlet),APILocator.getFileAssetAPI().fromContentlet(contentlet))){
RefreshMenus.deleteMenu(folder);
CacheLocator.getNavToolCache().removeNav(host.getIdentifier(), folder.getInode());
}
}
}
}
// clear possible CSS cache
CacheLocator.getCSSCache().remove(contIdent.getHostId(), contIdent.getURI(), true);
CacheLocator.getCSSCache().remove(contIdent.getHostId(), contIdent.getURI(), false);
}
if (contentlet.isLive()) {
publishAssociated(contentlet, isNewContent, createNewVersion);
} else {
if (!isNewContent) {
ContentletServices.invalidate(contentlet, true);
// writes the contentlet object to a file
ContentletMapServices.invalidate(contentlet, true);
}
indexAPI.addContentToIndex(contentlet);
}
if(structureHasAHostField && changedURI) {
DotConnect dc=new DotConnect();
dc.setSQL("select working_inode,live_inode from contentlet_version_info where identifier=? and lang<>?");
dc.addParam(contentlet.getIdentifier());
dc.addParam(contentlet.getLanguageId());
List<Map<String,Object>> others = dc.loadResults();
for(Map<String,Object> other : others) {
String workingi=(String)other.get("working_inode");
indexAPI.addContentToIndex(find(workingi,user,false));
String livei=(String)other.get("live_inode");
if(UtilMethods.isSet(livei) && !livei.equals(workingi))
indexAPI.addContentToIndex(find(livei,user,false));
}
}
// Set the properties again after the store on DB and before the fire on an Actionlet.
contentlet.setStringProperty("wfPublishDate", contentPushPublishDate);
contentlet.setStringProperty("wfPublishTime", contentPushPublishTime);
contentlet.setStringProperty("wfExpireDate", contentPushExpireDate);
contentlet.setStringProperty("wfExpireTime", contentPushExpireTime);
contentlet.setStringProperty("wfNeverExpire", contentPushNeverExpire);
contentlet.setStringProperty("whereToSend", contentWhereToSend);
contentlet.setStringProperty("forcePush", forcePush);
//wapi.
if(workflow!=null) {
workflow.setContentlet(contentlet);
wapi.fireWorkflowPostCheckin(workflow);
}
// DOTCMS-7290
DotCacheAdministrator cache = CacheLocator.getCacheAdministrator();