View Javadoc
1   /**
2    * Copyright 2005-2015 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.core.web.impex;
17  
18  import java.io.File;
19  import java.io.FileOutputStream;
20  import java.io.IOException;
21  import java.util.ArrayList;
22  import java.util.Collection;
23  import java.util.HashMap;
24  import java.util.List;
25  import java.util.Map;
26  
27  import javax.servlet.http.HttpServletRequest;
28  import javax.servlet.http.HttpServletResponse;
29  
30  import org.apache.commons.lang.exception.ExceptionUtils;
31  import org.apache.log4j.Logger;
32  import org.apache.struts.action.ActionForm;
33  import org.apache.struts.action.ActionForward;
34  import org.apache.struts.action.ActionMapping;
35  import org.apache.struts.upload.FormFile;
36  import org.kuali.rice.core.api.CoreApiServiceLocator;
37  import org.kuali.rice.core.api.impex.xml.CompositeXmlDocCollection;
38  import org.kuali.rice.core.api.impex.xml.FileXmlDocCollection;
39  import org.kuali.rice.core.api.impex.xml.XmlDoc;
40  import org.kuali.rice.core.api.impex.xml.XmlDocCollection;
41  import org.kuali.rice.core.api.impex.xml.ZipXmlDocCollection;
42  import org.kuali.rice.core.api.util.RiceConstants;
43  import org.kuali.rice.kim.api.KimConstants;
44  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
45  import org.kuali.rice.kns.web.struts.action.KualiAction;
46  import org.kuali.rice.krad.exception.AuthorizationException;
47  import org.kuali.rice.krad.util.GlobalVariables;
48  import org.kuali.rice.krad.util.KRADConstants;
49  import org.kuali.rice.krad.util.KRADUtils;
50  
51  /**
52   * Struts action that accepts uploaded files and feeds them to the XmlIngesterService
53   * @see org.kuali.rice.kew.batch.XmlIngesterService
54   * @see org.kuali.rice.core.web.impex.IngesterForm
55   * @author Kuali Rice Team (rice.collab@kuali.org)
56   */
57  public class IngesterAction extends KualiAction {
58      private static final Logger LOG = Logger.getLogger(IngesterAction.class);
59  
60      @Override
61  	public ActionForward execute(
62              ActionMapping mapping,
63              ActionForm form,
64              HttpServletRequest request,
65              HttpServletResponse response)
66              throws Exception {
67  
68      	checkAuthorization(form, "");
69      	
70      	if(isModuleLocked(form, "", request)) {
71      	    return mapping.findForward(RiceConstants.MODULE_LOCKED_MAPPING);
72      	}
73  
74          LOG.debug(request.getMethod());
75          if (!"post".equals(request.getMethod().toLowerCase())) {
76              LOG.debug("returning to view");
77              return mapping.findForward("view");
78          }
79  
80          IngesterForm iform = (IngesterForm) form;
81  
82          List<String> messages = new ArrayList<String>();
83          List<File> tempFiles = new ArrayList<File>();
84          try {
85              Collection<FormFile> files = iform.getFiles();
86              List<XmlDocCollection> collections = new ArrayList<XmlDocCollection>(files.size());
87              LOG.debug(files);
88              LOG.debug("" + files.size());
89  
90              for (FormFile file1 : files)
91              {
92                  if (file1.getFileName() == null || file1.getFileName().length() == 0) {
93  					continue;
94  				}
95                  if (file1.getFileData() == null)
96                  {
97                      messages.add("File '" + file1.getFileName() + "' contained no data");
98                      continue;
99                  }
100                 LOG.debug("Processing file: " + file1.getFileName());
101                 // ok, we have to copy it to *another* file because Struts doesn't give us a File
102                 // reference (which itself is not a bad abstraction) and XmlDocs based on ZipFile
103                 // can't be constructed without a file reference.
104                 FileOutputStream fos = null;
105                 File temp = null;
106                 try
107                 {
108                     temp = File.createTempFile("ingester", null);
109                     tempFiles.add(temp);
110                     fos = new FileOutputStream(temp);
111                     fos.write(file1.getFileData());
112                 } catch (IOException ioe)
113                 {
114                     messages.add("Error copying file data for '" + file1.getFileName() + "': " + ioe);
115                     continue;
116                 } finally
117                 {
118                     if (fos != null) {
119 						try
120 						{
121 						    fos.close();
122 						} catch (IOException ioe)
123 						{
124 						    LOG.error("Error closing temp file output stream: " + temp, ioe);
125 						}
126 					}
127                 }
128                 if (file1.getFileName().toLowerCase().endsWith(".zip"))
129                 {
130                     try
131                     {
132                         collections.add(new ZipXmlDocCollection(temp));
133                     } catch (IOException ioe)
134                     {
135                         String message = "Unable to load file: " + file1;
136                         LOG.error(message);
137                         messages.add(message);
138                     }
139                 } else if (file1.getFileName().endsWith(".xml"))
140                 {
141                     collections.add(new FileXmlDocCollection(temp, file1.getFileName()));
142                 } else
143                 {
144                     messages.add("Ignoring extraneous file: " + file1.getFileName());
145                 }
146             }
147 
148             if (collections.size() == 0) {
149                 String message = "No valid files to ingest";
150                 LOG.debug(message);
151                 messages.add(message);
152             } else {
153                 // wrap in composite collection to make transactional
154                 CompositeXmlDocCollection compositeCollection = new CompositeXmlDocCollection(collections);
155                 int totalProcessed = 0;
156                 List<XmlDocCollection> c = new ArrayList<XmlDocCollection>(1);
157                 c.add(compositeCollection);
158                 try {
159                     Collection<XmlDocCollection> failed = CoreApiServiceLocator.getXmlIngesterService().ingest(c, GlobalVariables.getUserSession().getPrincipalId());
160                     boolean txFailed = failed.size() > 0;
161                     if (txFailed) {
162                         messages.add("Ingestion failed");
163                     }
164                     for (XmlDocCollection collection1 : collections)
165                     {
166                         List<? extends XmlDoc> docs = collection1.getXmlDocs();
167                         for (XmlDoc doc1 : docs)
168                         {
169                             if (doc1.isProcessed())
170                             {
171                                 if (!txFailed)
172                                 {
173                                     totalProcessed++;
174                                     messages.add("Ingested xml doc: " + doc1.getName() + (doc1.getProcessingMessage() == null ? "" : "\n" + doc1.getProcessingMessage()));
175                                 } else
176                                 {
177                                     messages.add("Rolled back doc: " + doc1.getName() + (doc1.getProcessingMessage() == null ? "" : "\n" + doc1.getProcessingMessage()));
178                                 }
179                             } else
180                             {
181                                 messages.add("Failed to ingest xml doc: " + doc1.getName() + (doc1.getProcessingMessage() == null ? "" : "\n" + doc1.getProcessingMessage()));
182                             }
183                         }
184                     }
185                 } catch (Exception e) {
186                     String message = "Error during ingest";
187                     LOG.error(message, e);
188                     messages.add(message + ": " + e  + ":\n" + ExceptionUtils.getFullStackTrace(e));
189                 }
190                 if (totalProcessed == 0) {
191                     String message = "No xml docs ingested";
192                     LOG.debug(message);
193                     messages.add(message);
194                 }
195             }
196         } finally {
197             if (tempFiles.size() > 0) {
198                 for (File tempFile : tempFiles)
199                 {
200                     if (!tempFile.delete())
201                     {
202                         LOG.warn("Error deleting temp file: " + tempFile);
203                     }
204                 }
205             }
206         }
207 
208         request.setAttribute("messages", messages);
209         return mapping.findForward("view");
210     }
211 
212     @Override
213 	protected void checkAuthorization( ActionForm form, String methodToCall) throws AuthorizationException
214     {
215     	String principalId = GlobalVariables.getUserSession().getPrincipalId();
216     	Map<String, String> roleQualifier = new HashMap<String, String>();
217     	Map<String, String> permissionDetails = KRADUtils.getNamespaceAndActionClass(this.getClass());
218 
219         if (!KimApiServiceLocator.getPermissionService().isAuthorizedByTemplate(principalId,
220                 KRADConstants.KNS_NAMESPACE, KimConstants.PermissionTemplateNames.USE_SCREEN, permissionDetails,
221                 roleQualifier))
222         {
223             throw new AuthorizationException(GlobalVariables.getUserSession().getPrincipalName(),
224             		methodToCall,
225             		this.getClass().getSimpleName());
226         }
227     }
228 
229 
230 }