View Javadoc

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