1 package com.dotmarketing.portlets.contentlet.action; 2 3 import java.io.ByteArrayInputStream ; 4 import java.io.IOException ; 5 import java.io.InputStreamReader ; 6 import java.io.Reader ; 7 import java.text.ParseException ; 8 import java.text.SimpleDateFormat ; 9 import java.util.ArrayList ; 10 import java.util.HashMap ; 11 import java.util.HashSet ; 12 import java.util.List ; 13 14 import javax.portlet.ActionRequest; 15 import javax.portlet.ActionResponse; 16 import javax.portlet.PortletConfig; 17 import javax.servlet.http.HttpServletRequest ; 18 19 import org.apache.commons.beanutils.BeanUtils; 20 import org.apache.struts.action.ActionForm; 21 import org.apache.struts.action.ActionMapping; 22 23 import com.dotmarketing.beans.Host; 24 import com.dotmarketing.beans.Identifier; 25 import com.dotmarketing.beans.Permission; 26 import com.dotmarketing.cache.FieldsCache; 27 import com.dotmarketing.cache.IdentifierCache; 28 import com.dotmarketing.cms.factories.PublicRoleFactory; 29 import com.dotmarketing.db.DotHibernate; 30 import com.dotmarketing.exception.DotRuntimeException; 31 import com.dotmarketing.factories.HostFactory; 32 import com.dotmarketing.factories.InodeFactory; 33 import com.dotmarketing.factories.PermissionFactory; 34 import com.dotmarketing.factories.WebAssetFactory; 35 import com.dotmarketing.portal.struts.DotPortletAction; 36 import com.dotmarketing.portlets.contentlet.factories.ContentletFactory; 37 import com.dotmarketing.portlets.contentlet.model.Contentlet; 38 import com.dotmarketing.portlets.contentlet.struts.ImportContentletsForm; 39 import com.dotmarketing.portlets.languagesmanager.factories.LanguageFactory; 40 import com.dotmarketing.portlets.structure.factories.FieldFactory; 41 import com.dotmarketing.portlets.structure.factories.StructureFactory; 42 import com.dotmarketing.portlets.structure.model.Field; 43 import com.dotmarketing.portlets.structure.model.Structure; 44 import com.dotmarketing.services.ContentletServices; 45 import com.dotmarketing.util.Config; 46 import com.dotmarketing.util.Logger; 47 import com.dotmarketing.util.UtilMethods; 48 import com.dotmarketing.util.WebKeys; 49 import com.liferay.portal.model.Role; 50 import com.liferay.portal.model.User; 51 import com.liferay.portal.util.Constants; 52 import com.liferay.portal.util.PortalUtil; 53 import com.liferay.portlet.ActionRequestImpl; 54 import com.liferay.util.FileUtil; 55 import com.liferay.util.servlet.SessionMessages; 56 import com.liferay.util.servlet.UploadPortletRequest; 57 58 65 public class ImportContentletsAction extends DotPortletAction { 66 67 @SuppressWarnings ("unchecked") 68 public void processAction(ActionMapping mapping, ActionForm form, PortletConfig config, ActionRequest req, 69 ActionResponse res) throws Exception { 70 71 Logger.debug(this, "Import Contentlets Action"); 72 73 String cmd = req.getParameter(Constants.CMD); 74 String referer = req.getParameter("referer"); 75 76 Logger.debug(this, "ImportContentletsAction cmd=" + cmd); 77 78 User user = _getUser(req); 79 80 83 if ((cmd != null) && cmd.equals(com.dotmarketing.util.Constants.PREVIEW)) { 84 try { 85 Logger.debug(this, "Calling Preview Upload Method"); 86 87 UploadPortletRequest uploadReq = PortalUtil.getUploadPortletRequest(req); 89 byte[] bytes = FileUtil.getBytes(uploadReq.getFile("file")); 90 91 if (bytes == null || bytes.length == 0) { 92 SessionMessages.add(req, "message", "message.contentlet.file.required"); 93 setForward(req, "portlet.ext.contentlet.import_contentlets"); 94 } else { 95 _generatePreview(req, res, config, form, user, bytes); 96 setForward(req, "portlet.ext.contentlet.import_contentlets_preview"); 97 } 98 99 } catch (Exception ae) { 100 _handleException(ae, req); 101 return; 102 } 103 } else if ((cmd != null) && cmd.equals(com.dotmarketing.util.Constants.PUBLISH)) { 104 try { 105 Logger.debug(this, "Calling Process File Method"); 106 107 _processFile(req, res, config, form, user); 108 109 _sendToReferral(req, res, referer); 110 111 setForward(req, "portlet.ext.contentlet.import_contentlets_results"); 112 113 } catch (Exception ae) { 114 _handleException(ae, req); 115 return; 116 } 117 } else { 118 setForward(req, "portlet.ext.contentlet.import_contentlets"); 119 } 120 121 } 122 123 125 private void _generatePreview(ActionRequest req, ActionResponse res, PortletConfig config, ActionForm form, 126 User user, byte[] bytes) throws Exception { 127 128 ActionRequestImpl reqImpl = (ActionRequestImpl) req; 130 HttpServletRequest httpReq = reqImpl.getHttpServletRequest(); 131 132 httpReq.getSession().setAttribute("file_to_import", bytes); 133 httpReq.getSession().setAttribute("form_to_import", form); 134 135 ImportContentletsForm importForm = (ImportContentletsForm) form; 136 137 HashMap results = importFile(bytes, importForm.getStructure(), importForm.getFields(), true, user); 138 139 req.setAttribute("previewResults", results); 140 } 141 142 private void _processFile(ActionRequest req, ActionResponse res, PortletConfig config, ActionForm form, User user) 143 throws Exception { 144 145 ActionRequestImpl reqImpl = (ActionRequestImpl) req; 147 HttpServletRequest httpReq = reqImpl.getHttpServletRequest(); 148 149 byte[] bytes = (byte[]) httpReq.getSession().getAttribute("file_to_import"); 150 ImportContentletsForm importForm = (ImportContentletsForm) httpReq.getSession().getAttribute("form_to_import"); 151 152 HashMap results = importFile(bytes, importForm.getStructure(), importForm.getFields(), false, user); 153 154 req.setAttribute("importResults", results); 155 } 156 157 private String lineToString(String [] line) { 159 StringBuffer returnSt = new StringBuffer (); 160 for (String st : line) { 161 returnSt.append(st + ","); 162 } 163 return returnSt.toString(); 164 } 165 166 private Host defaultHost = HostFactory.getDefaultHost(); 167 168 private HashMap <Integer , Field> headers; 170 private HashMap <Integer , Field> keyFields; 171 172 private int newContentCounter; 174 private int contentToUpdateCounter; 175 176 private int contentUpdated; 178 private int contentCreated; 179 private HashSet keyContentUpdated = new HashSet (); 180 181 private int commitGranularity = 10; 182 private int sleepTime = 200; 183 private Role CMSAdmin; 184 private List <Permission> structurePermissions; 185 186 private HashMap importFile(byte[] bytes, long structure, long[] keyfields, boolean preview, User user) 187 throws DotRuntimeException { 188 189 HashMap <String , List <String >> results = new HashMap (); 190 results.put("warnings", new ArrayList <String >()); 191 results.put("errors", new ArrayList <String >()); 192 results.put("messages", new ArrayList <String >()); 193 results.put("results", new ArrayList <String >()); 194 195 Structure st = StructureFactory.getStructureByInode(structure); 196 try { 197 CMSAdmin = PublicRoleFactory.getCMSAdminRole(); 198 } catch (Exception e1) { 199 Logger.error (this, "importFile: failed retrieving the CMSAdmin role.", e1); 200 throw new DotRuntimeException (e1.getMessage()); 201 } 202 structurePermissions = PermissionFactory.getPermissions(st); 203 204 int lines = 0; 206 int errors = 0; 207 int lineNumber = 0; 208 newContentCounter = 0; 209 contentToUpdateCounter = 0; 210 contentCreated = 0; 211 contentUpdated = 0; 212 keyContentUpdated = new HashSet (); 213 214 headers = new HashMap <Integer , Field> (); 215 keyFields = new HashMap <Integer , Field> (); 216 217 218 Reader reader = null; 220 try { 221 reader = new InputStreamReader (new ByteArrayInputStream (bytes)); 222 List <String []> linesToRead = UtilMethods.specialSplit(reader, ',', '"'); 223 224 if (linesToRead.size() > 0) { 225 226 importHeaders(linesToRead.get(0), st, keyfields, preview, user, results); 228 linesToRead.remove(0); 229 lineNumber++; 230 231 if (headers.size() > 0) { 233 234 if (!preview) 235 DotHibernate.startTransaction(); 236 237 for (String [] lineToRead : linesToRead) { 238 lineNumber++; 239 try { 240 lines++; 241 Logger.debug(this, "Line " + lines + ": (" + lineToString(lineToRead) + ")."); 242 importLine(lineToRead, st, preview, user, results, lineNumber); 244 245 if (!preview && (lineNumber % commitGranularity == 0)) { 246 DotHibernate.commitTransaction(); 247 DotHibernate.startTransaction(); 248 } 249 250 if (!preview) 251 Thread.sleep(sleepTime); 252 } catch (DotRuntimeException ex) { 253 errors++; 254 Logger.debug(this, "Error line: " + lines + " (" + lineToString(lineToRead) 255 + "). Line Ignored."); 256 } 257 } 258 259 if(!preview) 260 DotHibernate.commitTransaction(); 261 262 results.get("messages").add(lines + " lines of data were read."); 263 if (errors > 0) 264 results.get("errors").add(errors + " input lines had errors."); 265 if (newContentCounter > 0) 266 results.get("messages").add("Approximately " + (newContentCounter) + " new content will be created."); 267 if (contentToUpdateCounter > 0) 268 results.get("messages").add("Approximately " + (contentToUpdateCounter) + " old content will be updated."); 269 270 if (contentCreated > 0) 271 results.get("results").add(contentCreated + " new \"" + st.getName() + "\" were created."); 272 if (contentUpdated > 0) 273 results.get("results").add(contentUpdated + " \"" + st.getName() + "\" were updated."); 274 275 } else { 276 results.get("errors").add("No headers found on the file, nothing will be imported."); 277 } 278 } 279 } catch (Exception e) { 280 e.printStackTrace(System.out); 281 } finally { 282 if (reader != null) 283 try { 284 reader.close(); 285 } catch (IOException e) { 286 287 } 288 } 289 Logger.info(this, lines + " lines read correctly. " + errors + " errors found."); 290 291 return results; 292 } 293 294 private void importHeaders(String [] headerLine, Structure structure, long[] keyFieldsInodes, boolean preview, 295 User user, HashMap <String , List <String >> results) throws DotRuntimeException { 296 297 int importableFields = 0; 298 299 List <Field> fields = FieldsCache.getFieldsByStructureInode(structure.getInode()); 301 for (int i = 0; i < headerLine.length; i++) { 302 boolean found = false; 303 String header = headerLine[i]; 304 for (Field field : fields) { 305 if (field.getFieldName().equals(header)) { 306 if (field.getFieldType().equals(WebKeys.TypeField.BUTTON)) 307 results.get("warnings").add( 308 "Header: \"" + header 309 + "\" matches a field of type button, this column of data will be ignored."); 310 else if (field.getFieldType().equals(WebKeys.TypeField.FILE)) 311 results.get("warnings").add( 312 "Header: \"" + header 313 + "\" matches a field of type file, this column of data will be ignored."); 314 else if (field.getFieldType().equals(WebKeys.TypeField.IMAGE)) 315 results.get("warnings").add( 316 "Header: \"" + header 317 + "\" matches a field of type image, this column of data will be ignored."); 318 else if (field.getFieldType().equals(WebKeys.TypeField.LINK)) 319 results.get("warnings").add( 320 "Header: \"" + header 321 + "\" matches a field of type link, this column of data will be ignored."); 322 else { 323 found = true; 324 headers.put(i, field); 325 for (long fieldInode : keyFieldsInodes) { 326 if (fieldInode == field.getInode()) 327 keyFields.put(i, field); 328 } 329 break; 330 } 331 } 332 } 333 if (!found) { 334 results.get("warnings").add( 335 "Header: \"" + header 336 + "\" doesn't match any structure field, this column of data will be ignored."); 337 } 338 } 339 340 for (Field field : fields) { 341 if (!(field.getFieldType().equals(WebKeys.TypeField.BUTTON) && 342 field.getFieldType().equals(WebKeys.TypeField.FILE) && 343 field.getFieldType().equals(WebKeys.TypeField.IMAGE) && 344 field.getFieldType().equals(WebKeys.TypeField.LINK))) 345 importableFields++; 346 } 347 348 for (long keyField : keyFieldsInodes) { 350 boolean found = false; 351 for (Field headerField : headers.values()) { 352 if (headerField.getInode() == keyField) { 353 found = true; 354 break; 355 } 356 } 357 if (!found) { 358 results.get("errors").add( 359 "Key field: \"" + FieldFactory.getFieldByInode(keyField).getFieldName() 360 + "\" choosen doesn't match any of the headers found in the file."); 361 } 362 } 363 364 if (keyFieldsInodes.length == 0) 365 results.get("warnings").add( 366 "No key fields were choosen, it could give to you duplicated content."); 367 368 if (importableFields == headers.size()) { 370 results.get("messages").add( 371 "All the " + headers.size() + " headers found on the file matches all the structure fields."); 372 } else { 373 if (headers.size() > 0) 374 results.get("messages").add(headers.size() + " headers found on the file matches the structure fields."); 375 else 376 results 377 .get("messages") 378 .add( 379 "No headers found on the file that match any of the structure fields. The process will not import anything."); 380 results 381 .get("warnings") 382 .add("Not all the structure fields were matched against the file headers. Some content fields could be left empty."); 383 } 384 } 385 386 private void importLine(String [] line, Structure structure, boolean preview, User user, 387 HashMap <String , List <String >> results, int lineNumber) throws DotRuntimeException { 388 389 try { 390 HashMap <Integer , Object > values = new HashMap <Integer , Object >(); 392 for (Integer column : headers.keySet()) { 393 Field field = headers.get(column); 394 if (line.length < column) { 395 throw new DotRuntimeException("Incomplete line found, the line #" + lineNumber + 396 " doesn't contain all the required columns."); 397 } 398 String value = line[column]; 399 Object valueObj = value; 400 if (field.getFieldType().equals(WebKeys.TypeField.DATE)) { 401 SimpleDateFormat formatter = new SimpleDateFormat (WebKeys.DateFormats.EXP_IMP_DATE); 402 try { 403 if (field.getFieldContentlet().startsWith("date")) 404 valueObj = formatter.parse(value); 405 } catch (ParseException e) { 406 throw new DotRuntimeException("Line #" + lineNumber + " contains errors, Column: " + field.getFieldName() + 407 ", value: " + value + ", couldn't be parsed as a date format: " + WebKeys.DateFormats.EXP_IMP_DATE); 408 } 409 } else if (field.getFieldType().equals(WebKeys.TypeField.DATETIME)) { 410 SimpleDateFormat formatter = new SimpleDateFormat (WebKeys.DateFormats.EXP_IMP_DATETIME); 411 try { 412 if (field.getFieldContentlet().startsWith("date")) 413 valueObj = formatter.parse(value); 414 } catch (ParseException e) { 415 throw new DotRuntimeException("Line #" + lineNumber + " contains errors, Column: " + field.getFieldName() + 416 ", value: " + value + ", couldn't be parsed as a date format: " + WebKeys.DateFormats.EXP_IMP_DATETIME); 417 } 418 } else if (field.getFieldType().equals(WebKeys.TypeField.TIME)) { 419 SimpleDateFormat formatter = new SimpleDateFormat (WebKeys.DateFormats.EXP_IMP_TIME); 420 try { 421 if (field.getFieldContentlet().startsWith("date")) 422 valueObj = formatter.parse(value); 423 } catch (ParseException e) { 424 throw new DotRuntimeException("Line #" + lineNumber + " contains errors, Column: " + field.getFieldName() + 425 ", value: " + value + ", couldn't be parsed as a date format: " + WebKeys.DateFormats.EXP_IMP_TIME); 426 } 427 } else if (field.getFieldType().equals(WebKeys.TypeField.TEXT)) { 428 if (value.length() > 255) 429 value = value.substring(0, 255); 430 valueObj = value; 431 } else { 432 valueObj = value; 433 } 434 values.put(column, valueObj); 435 } 436 437 List <Contentlet> contentlets = new ArrayList <Contentlet>(); 439 HashMap conditionMap = new HashMap (); 440 String conditionValues = ""; 441 if (keyFields.size() > 0) { 442 443 for (Integer column : keyFields.keySet()) { 444 Field field = keyFields.get(column); 445 Object value = values.get(column); 446 conditionMap.put(field.getFieldName(), value); 447 conditionValues += conditionValues + value + "-"; 448 } 449 contentlets = ContentletFactory.getContentletsByStuctureAndFieldsValues(structure, conditionMap); 450 } 451 452 boolean isNew = false; 454 if (contentlets.size() == 0) { 455 newContentCounter++; 456 isNew = true; 457 if (!preview) { 458 Contentlet newCont = new Contentlet(); 459 WebAssetFactory.createAsset(newCont, user.getUserId()); 460 newCont.setLive(true); 461 newCont.setWorking(true); 462 newCont.setStructureInode(structure.getInode()); 463 newCont.setTitle(""); 464 newCont.setFriendlyName(""); 465 newCont.setLanguageId(LanguageFactory.getLanguage (Config.getStringProperty("DEFAULT_LANGUAGE_CODE"), 466 Config.getStringProperty("DEFAULT_LANGUAGE_COUNTRY_CODE")).getId()); 467 contentlets.add(newCont); 468 } 469 } else { 470 if (conditionValues.equals("") || !keyContentUpdated.contains(conditionValues)) { 471 contentToUpdateCounter += contentlets.size(); 472 if (preview) 473 keyContentUpdated.add(conditionValues); 474 } 475 if (contentlets.size() > 1) { 476 results.get("warnings").add( 477 "The key fields choosen match more than one content, in this case: " + conditionMap 478 + " matches: " + contentlets.size() + " different contents, looks like the key fields choosen " + 479 "aren't a real key."); 480 } 481 482 } 483 484 if (!preview) { 485 for (Contentlet cont : contentlets) { 486 487 for (Integer column : headers.keySet()) { 488 Field field = headers.get(column); 489 Object value = values.get(column); 490 BeanUtils.setProperty(cont, field.getFieldContentlet(), value); 491 } 492 493 InodeFactory.saveInode(cont); 494 495 ContentletServices.writeContentletToFile(cont, true); 496 if (cont.isLive()) 497 ContentletServices.writeContentletToFile(cont, false); 498 499 if (isNew) { 500 501 Identifier id = IdentifierCache.getIdentifierByInodeFromCache(cont.getInode()); 502 503 Permission permission = new Permission(id.getInode(), Integer.parseInt(CMSAdmin.getRoleId()), 505 Config.getIntProperty("PERMISSION_READ")); 506 PermissionFactory.savePermission(permission); 507 permission = new Permission(id.getInode(), Integer.parseInt(CMSAdmin.getRoleId()), Config 508 .getIntProperty("PERMISSION_WRITE")); 509 PermissionFactory.savePermission(permission); 510 permission = new Permission(id.getInode(), Integer.parseInt(CMSAdmin.getRoleId()), Config 511 .getIntProperty("PERMISSION_PUBLISH")); 512 PermissionFactory.savePermission(permission); 513 514 for (Permission p : structurePermissions) { 516 permission = new Permission(id.getInode(), p.getRoleId(), p.getPermission()); 517 PermissionFactory.savePermission(permission); 518 } 519 520 defaultHost.addChild(cont); 521 } 522 523 ContentletFactory.reIndexContentlet(cont); 524 if (isNew) 525 contentCreated++; 526 else 527 if (conditionValues.equals("") || !keyContentUpdated.contains(conditionValues)) { 528 contentUpdated++; 529 keyContentUpdated.add(conditionValues); 530 } 531 } 532 } 533 534 } catch (Exception e) { 535 throw new DotRuntimeException(e.getMessage()); 536 } 537 538 } 539 540 } 541 | Popular Tags |