KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > dotmarketing > portlets > contentlet > action > ImportContentletsAction


1 package com.dotmarketing.portlets.contentlet.action;
2
3 import java.io.ByteArrayInputStream JavaDoc;
4 import java.io.IOException JavaDoc;
5 import java.io.InputStreamReader JavaDoc;
6 import java.io.Reader JavaDoc;
7 import java.text.ParseException JavaDoc;
8 import java.text.SimpleDateFormat JavaDoc;
9 import java.util.ArrayList JavaDoc;
10 import java.util.HashMap JavaDoc;
11 import java.util.HashSet JavaDoc;
12 import java.util.List JavaDoc;
13
14 import javax.portlet.ActionRequest;
15 import javax.portlet.ActionResponse;
16 import javax.portlet.PortletConfig;
17 import javax.servlet.http.HttpServletRequest JavaDoc;
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 /**
59  * This action class import content from csv/text files.
60  * The csv file should contains as first line the required headers that match the structure fields
61  *
62  * @author david
63  *
64  */

65 public class ImportContentletsAction extends DotPortletAction {
66
67     @SuppressWarnings JavaDoc("unchecked")
68     public void processAction(ActionMapping mapping, ActionForm form, PortletConfig config, ActionRequest req,
69             ActionResponse res) throws Exception JavaDoc {
70
71         Logger.debug(this, "Import Contentlets Action");
72
73         String JavaDoc cmd = req.getParameter(Constants.CMD);
74         String JavaDoc referer = req.getParameter("referer");
75
76         Logger.debug(this, "ImportContentletsAction cmd=" + cmd);
77
78         User user = _getUser(req);
79
80         /*
81          * We are submiting the file to process
82          */

83         if ((cmd != null) && cmd.equals(com.dotmarketing.util.Constants.PREVIEW)) {
84             try {
85                 Logger.debug(this, "Calling Preview Upload Method");
86
87                 //Validation
88
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 JavaDoc 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 JavaDoc ae) {
114                 _handleException(ae, req);
115                 return;
116             }
117         } else {
118             setForward(req, "portlet.ext.contentlet.import_contentlets");
119         }
120
121     }
122
123     // /// ************** ALL METHODS HERE *************************** ////////
124

125     private void _generatePreview(ActionRequest req, ActionResponse res, PortletConfig config, ActionForm form,
126             User user, byte[] bytes) throws Exception JavaDoc {
127
128         // wraps request to get session object
129
ActionRequestImpl reqImpl = (ActionRequestImpl) req;
130         HttpServletRequest JavaDoc 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 JavaDoc 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 JavaDoc {
144
145         // wraps request to get session object
146
ActionRequestImpl reqImpl = (ActionRequestImpl) req;
147         HttpServletRequest JavaDoc 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 JavaDoc results = importFile(bytes, importForm.getStructure(), importForm.getFields(), false, user);
153
154         req.setAttribute("importResults", results);
155     }
156
157     //Utility method
158
private String JavaDoc lineToString(String JavaDoc[] line) {
159         StringBuffer JavaDoc returnSt = new StringBuffer JavaDoc();
160         for (String JavaDoc st : line) {
161             returnSt.append(st + ",");
162         }
163         return returnSt.toString();
164     }
165
166     private Host defaultHost = HostFactory.getDefaultHost();
167     
168     //Temp maps used to parse the file
169
private HashMap JavaDoc<Integer JavaDoc, Field> headers;
170     private HashMap JavaDoc<Integer JavaDoc, Field> keyFields;
171     
172     //Counters for the preview page
173
private int newContentCounter;
174     private int contentToUpdateCounter;
175     
176     //Counters for the results page
177
private int contentUpdated;
178     private int contentCreated;
179     private HashSet JavaDoc keyContentUpdated = new HashSet JavaDoc ();
180
181     private int commitGranularity = 10;
182     private int sleepTime = 200;
183     private Role CMSAdmin;
184     private List JavaDoc<Permission> structurePermissions;
185     
186     private HashMap JavaDoc importFile(byte[] bytes, long structure, long[] keyfields, boolean preview, User user)
187             throws DotRuntimeException {
188
189         HashMap JavaDoc<String JavaDoc, List JavaDoc<String JavaDoc>> results = new HashMap JavaDoc();
190         results.put("warnings", new ArrayList JavaDoc<String JavaDoc>());
191         results.put("errors", new ArrayList JavaDoc<String JavaDoc>());
192         results.put("messages", new ArrayList JavaDoc<String JavaDoc>());
193         results.put("results", new ArrayList JavaDoc<String JavaDoc>());
194
195         Structure st = StructureFactory.getStructureByInode(structure);
196         try {
197             CMSAdmin = PublicRoleFactory.getCMSAdminRole();
198         } catch (Exception JavaDoc 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         //Initializing variables
205
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 JavaDoc ();
213         
214         headers = new HashMap JavaDoc<Integer JavaDoc, Field> ();
215         keyFields = new HashMap JavaDoc<Integer JavaDoc, Field> ();
216         
217         
218         //Parsing the file line per line
219
Reader JavaDoc reader = null;
220         try {
221             reader = new InputStreamReader JavaDoc(new ByteArrayInputStream JavaDoc(bytes));
222             List JavaDoc<String JavaDoc[]> linesToRead = UtilMethods.specialSplit(reader, ',', '"');
223
224             if (linesToRead.size() > 0) {
225                 
226                 //Importing headers from the first file line
227
importHeaders(linesToRead.get(0), st, keyfields, preview, user, results);
228                 linesToRead.remove(0);
229                 lineNumber++;
230                 
231                 //Reading the whole file
232
if (headers.size() > 0) {
233                     
234                     if (!preview)
235                         DotHibernate.startTransaction();
236                     
237                     for (String JavaDoc[] lineToRead : linesToRead) {
238                         lineNumber++;
239                         try {
240                             lines++;
241                             Logger.debug(this, "Line " + lines + ": (" + lineToString(lineToRead) + ").");
242                             //Importing a line
243
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 JavaDoc e) {
280             e.printStackTrace(System.out);
281         } finally {
282             if (reader != null)
283                 try {
284                     reader.close();
285                 } catch (IOException JavaDoc 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 JavaDoc[] headerLine, Structure structure, long[] keyFieldsInodes, boolean preview,
295             User user, HashMap JavaDoc<String JavaDoc, List JavaDoc<String JavaDoc>> results) throws DotRuntimeException {
296         
297         int importableFields = 0;
298         
299         //Importing headers and storing them in a hashmap to be reused later in the whole import process
300
List JavaDoc<Field> fields = FieldsCache.getFieldsByStructureInode(structure.getInode());
301         for (int i = 0; i < headerLine.length; i++) {
302             boolean found = false;
303             String JavaDoc 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         //Checking keyField selected by the user against the headers
349
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         //Adding some messages to the results
369
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 JavaDoc[] line, Structure structure, boolean preview, User user,
387             HashMap JavaDoc<String JavaDoc, List JavaDoc<String JavaDoc>> results, int lineNumber) throws DotRuntimeException {
388
389         try {
390             //Building a values hashmap based on the headers/columns position
391
HashMap JavaDoc<Integer JavaDoc, Object JavaDoc> values = new HashMap JavaDoc<Integer JavaDoc, Object JavaDoc>();
392             for (Integer JavaDoc 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 JavaDoc value = line[column];
399                 Object JavaDoc valueObj = value;
400                 if (field.getFieldType().equals(WebKeys.TypeField.DATE)) {
401                     SimpleDateFormat JavaDoc formatter = new SimpleDateFormat JavaDoc(WebKeys.DateFormats.EXP_IMP_DATE);
402                     try {
403                         if (field.getFieldContentlet().startsWith("date"))
404                             valueObj = formatter.parse(value);
405                     } catch (ParseException JavaDoc 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 JavaDoc formatter = new SimpleDateFormat JavaDoc(WebKeys.DateFormats.EXP_IMP_DATETIME);
411                     try {
412                         if (field.getFieldContentlet().startsWith("date"))
413                             valueObj = formatter.parse(value);
414                     } catch (ParseException JavaDoc 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 JavaDoc formatter = new SimpleDateFormat JavaDoc(WebKeys.DateFormats.EXP_IMP_TIME);
420                     try {
421                         if (field.getFieldContentlet().startsWith("date"))
422                             valueObj = formatter.parse(value);
423                     } catch (ParseException JavaDoc 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             //Searching contentlets to be updated by key fields
438
List JavaDoc<Contentlet> contentlets = new ArrayList JavaDoc<Contentlet>();
439             HashMap JavaDoc conditionMap = new HashMap JavaDoc();
440             String JavaDoc conditionValues = "";
441             if (keyFields.size() > 0) {
442
443                 for (Integer JavaDoc column : keyFields.keySet()) {
444                     Field field = keyFields.get(column);
445                     Object JavaDoc value = values.get(column);
446                     conditionMap.put(field.getFieldName(), value);
447                     conditionValues += conditionValues + value + "-";
448                 }
449                 contentlets = ContentletFactory.getContentletsByStuctureAndFieldsValues(structure, conditionMap);
450             }
451
452             //Creating/updating content
453
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 JavaDoc column : headers.keySet()) {
488                         Field field = headers.get(column);
489                         Object JavaDoc 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                         //setting the cmsadmin permissions
504
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                         //setting the default structure permissions
515
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 JavaDoc e) {
535             throw new DotRuntimeException(e.getMessage());
536         }
537
538     }
539
540 }
541
Popular Tags