/**
* Licensed to Apereo under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright ownership. Apereo
* licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use
* this file except in compliance with the License. You may obtain a copy of the License at the
* following location:
*
* <p>http://www.apache.org/licenses/LICENSE-2.0
*
* <p>Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apereo.portal.rest;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.StartElement;
import javax.xml.transform.stax.StAXSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apereo.portal.EntityIdentifier;
import org.apereo.portal.io.xml.IPortalDataHandlerService;
import org.apereo.portal.io.xml.PortalDataKey;
import org.apereo.portal.security.IAuthorizationPrincipal;
import org.apereo.portal.security.IPermission;
import org.apereo.portal.security.IPerson;
import org.apereo.portal.security.IPersonManager;
import org.apereo.portal.services.AuthorizationService;
import org.apereo.portal.xml.StaxUtils;
import org.apereo.portal.xml.XmlUtilities;
import org.apereo.portal.xml.stream.BufferedXMLEventReader;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.XML;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
/**
* ImportExportController provides AJAX/REST targets for import/export operations.
*
*/
@Controller
public class ImportExportController {
final Log log = LogFactory.getLog(getClass());
private IPersonManager personManager;
private IPortalDataHandlerService portalDataHandlerService;
private XmlUtilities xmlUtilities;
@Autowired
public void setXmlUtilities(XmlUtilities xmlUtilities) {
this.xmlUtilities = xmlUtilities;
}
@Autowired
public void setPersonManager(IPersonManager personManager) {
this.personManager = personManager;
}
@Autowired
public void setPortalDataHandlerService(IPortalDataHandlerService portalDataHandlerService) {
this.portalDataHandlerService = portalDataHandlerService;
}
@RequestMapping(value = "/import", method = RequestMethod.POST)
public void importEntity(
@RequestParam("file") MultipartFile entityFile,
HttpServletRequest request,
HttpServletResponse response)
throws IOException, XMLStreamException {
//Get a StAX reader for the source to determine info about the data to import
final BufferedXMLEventReader bufferedXmlEventReader =
createSourceXmlEventReader(entityFile);
final PortalDataKey portalDataKey = getPortalDataKey(bufferedXmlEventReader);
final IPerson person = personManager.getPerson(request);
final EntityIdentifier ei = person.getEntityIdentifier();
final IAuthorizationPrincipal ap =
AuthorizationService.instance().newPrincipal(ei.getKey(), ei.getType());
if (!ap.hasPermission(
"UP_SYSTEM", "IMPORT_ENTITY", portalDataKey.getName().getLocalPart())) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return;
}
portalDataHandlerService.importData(new StAXSource(bufferedXmlEventReader));
response.setStatus(HttpServletResponse.SC_OK);
}
protected BufferedXMLEventReader createSourceXmlEventReader(MultipartFile multipartFile)
throws IOException {
final InputStream inputStream = multipartFile.getInputStream();
final String name = multipartFile.getOriginalFilename();
final XMLInputFactory xmlInputFactory = this.xmlUtilities.getXmlInputFactory();
final XMLEventReader xmlEventReader;
try {
xmlEventReader = xmlInputFactory.createXMLEventReader(name, inputStream);
} catch (XMLStreamException e) {
throw new RuntimeException("Failed to create XML Event Reader for data Source", e);
}
return new BufferedXMLEventReader(xmlEventReader, -1);
}
protected PortalDataKey getPortalDataKey(final BufferedXMLEventReader bufferedXmlEventReader) {
final StartElement rootElement = StaxUtils.getRootElement(bufferedXmlEventReader);
final PortalDataKey portalDataKey = new PortalDataKey(rootElement);
bufferedXmlEventReader.reset();
return portalDataKey;
}
/**
* Delete an uPortal database object. This method provides a REST interface for uPortal database
* object deletion.
*
* <p>The path for this method is /entity/type/identifier. The identifier generally a string
* that may be used as a unique identifier, but is dependent on the entity type. For example, to
* delete the "demo" user one might use the path /entity/user/demo.
*/
@RequestMapping(value = "/entity/{entityType}/{entityId}", method = RequestMethod.DELETE)
public void deleteEntity(
@PathVariable("entityType") String entityType,
@PathVariable("entityId") String entityId,
HttpServletRequest request,
HttpServletResponse response)
throws IOException {
final IPerson person = personManager.getPerson(request);
final EntityIdentifier ei = person.getEntityIdentifier();
final IAuthorizationPrincipal ap =
AuthorizationService.instance().newPrincipal(ei.getKey(), ei.getType());
if (!ap.hasPermission(IPermission.PORTAL_SYSTEM, IPermission.DELETE_ACTIVITY, entityType)) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return;
}
// get the task associated with exporting this entity type
portalDataHandlerService.deleteData(entityType, entityId);
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
}
@RequestMapping(value = "/entity/{entityType}/{entityId}", method = RequestMethod.GET)
public void exportEntity(
@PathVariable("entityId") String entityId,
@PathVariable("entityType") String entityType,
@RequestParam(value = "download", required = false) boolean download,
@RequestParam(value = "format", defaultValue = "XML", required = false)
String formatType,
HttpServletRequest request,
HttpServletResponse response)
throws IOException, JSONException {
final IPerson person = personManager.getPerson(request);
final EntityIdentifier ei = person.getEntityIdentifier();
final IAuthorizationPrincipal ap =
AuthorizationService.instance().newPrincipal(ei.getKey(), ei.getType());
// if the current user does not have permission to delete this database
// object type, return a 401 error code
if (!ap.hasPermission(IPermission.PORTAL_SYSTEM, IPermission.EXPORT_ACTIVITY, entityType)) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return;
}
//Export the data into a string buffer
final StringWriter exportBuffer = new StringWriter();
final String fileName =
portalDataHandlerService.exportData(
entityType, entityId, new StreamResult(exportBuffer));
final PrintWriter responseWriter = response.getWriter();
if (download) {
response.setHeader(
"Content-Disposition",
"attachment; filename=\""
+ fileName
+ "."
+ entityType
+ "."
+ formatType.toLowerCase()
+ "\"");
}
if ("XML".equalsIgnoreCase(formatType)) {
responseWriter.print(exportBuffer.getBuffer());
} else if ("JSON".equalsIgnoreCase(formatType)) {
JSONObject json = XML.toJSONObject(exportBuffer.getBuffer().toString());
responseWriter.print(json);
} else {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return;
}
}
}