blob: 13d687039846e2b00a038dda56c2ad5be82012a2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010-2014 SAP AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* SAP AG - initial API and implementation
*******************************************************************************/
package org.eclipse.skalli.core.rest.admin;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import org.apache.commons.io.IOUtils;
import org.eclipse.skalli.commons.Statistics;
import org.eclipse.skalli.commons.Statistics.BrowserInfo;
import org.eclipse.skalli.commons.Statistics.RefererInfo;
import org.eclipse.skalli.commons.Statistics.ResponseTimeInfo;
import org.eclipse.skalli.commons.Statistics.SearchInfo;
import org.eclipse.skalli.commons.Statistics.UsageInfo;
import org.eclipse.skalli.commons.Statistics.UserInfo;
import org.eclipse.skalli.services.extension.rest.ResourceBase;
import org.eclipse.skalli.services.extension.rest.ResourceRepresentation;
import org.eclipse.skalli.services.permit.Permits;
import org.restlet.data.Disposition;
import org.restlet.data.MediaType;
import org.restlet.data.Status;
import org.restlet.representation.OutputRepresentation;
import org.restlet.representation.Representation;
import org.restlet.resource.Get;
import org.restlet.resource.Put;
import com.thoughtworks.xstream.XStreamException;
public class StatisticsBackupResource extends ResourceBase {
private static final String FILE_NAME = "statistics.zip"; //$NON-NLS-1$
private static final String ENTRY_NAME = "statistics.xml"; //$NON-NLS-1$
private static final String ID_PREFIX = "rest:api/admin/statistics/backup:"; //$NON-NLS-1$
private static final String ERROR_ID_IO_ERROR = ID_PREFIX + "00"; //$NON-NLS-1$
private static final String ERROR_ID_INVALID_BACKUP = ID_PREFIX + ":30"; //$NON-NLS-1$
private static final String ERROR_ID_PARSING_FAILED = ID_PREFIX + ":40"; //$NON-NLS-1$
private static final String ERROR_ID_CLASS_MISMATCH = ID_PREFIX + ":50"; //$NON-NLS-1$
@Get
public Representation backup() {
if (!Permits.isAllowed(getAction(), getPath())) {
return createUnauthorizedRepresentation();
}
StatisticsQuery query = new StatisticsQuery(getQueryAttributes());
Statistics statistics = new Statistics(Statistics.getDefault(), query.getFrom(), query.getTo());
ZipOutputRepresentation zipRepresentation = new ZipOutputRepresentation(statistics);
Disposition disposition = new Disposition(Disposition.TYPE_ATTACHMENT);
disposition.setFilename(FILE_NAME);
zipRepresentation.setDisposition(disposition);
return zipRepresentation;
}
@Put
public Representation restore(Representation entity) {
if (!Permits.isAllowed(getAction(), getPath())) {
return createUnauthorizedRepresentation();
}
ZipInputStream zipStream = null;
try {
zipStream = new ZipInputStream(entity.getStream());
ZipEntry entry = zipStream.getNextEntry();
try {
String entryName = entry.getName();
if (!entryName.equals(ENTRY_NAME)) {
return createErrorRepresentation(Status.CLIENT_ERROR_BAD_REQUEST, ERROR_ID_INVALID_BACKUP,
"Invalid backup file: Expected entry ''statistics.xml'', but found ''{0}''", entryName); //$NON-NLS-1$
}
ResourceRepresentation<Statistics> representation = new ResourceRepresentation<Statistics>();
addAliases(representation);
Statistics.getDefault().restore(representation.read(zipStream, Statistics.class));
} finally {
zipStream.closeEntry();
}
} catch (IOException e) {
return createIOErrorRepresentation(ERROR_ID_IO_ERROR, e);
} catch (XStreamException e) {
return createErrorRepresentation(Status.CLIENT_ERROR_BAD_REQUEST, ERROR_ID_PARSING_FAILED,
"Invalid backup file: {0}", e.getMessage()); //$NON-NLS-1$
} catch (ClassCastException e) {
return createErrorRepresentation(Status.CLIENT_ERROR_BAD_REQUEST, ERROR_ID_CLASS_MISMATCH,
"Invalid backup file: {0}", e.getMessage()); //$NON-NLS-1$
} finally {
IOUtils.closeQuietly(zipStream);
}
setStatus(Status.SUCCESS_NO_CONTENT);
return null;
}
private static class ZipOutputRepresentation extends OutputRepresentation {
private Statistics statistics;
public ZipOutputRepresentation(Statistics statistics) {
super(MediaType.APPLICATION_ZIP);
this.statistics = statistics;
}
@Override
public void write(OutputStream out) throws IOException {
ZipOutputStream zipStream = null;
try {
zipStream = new ZipOutputStream(new BufferedOutputStream(out));
ZipEntry entry = new ZipEntry(ENTRY_NAME);
zipStream.putNextEntry(entry);
ResourceRepresentation<Statistics> representation = new ResourceRepresentation<Statistics>(statistics);
addAliases(representation);
representation.write(zipStream);
} finally {
IOUtils.closeQuietly(zipStream);
}
}
}
@SuppressWarnings("nls")
private static void addAliases(ResourceRepresentation<Statistics> representation) {
representation.addAlias("statistics", Statistics.class);
representation.addAlias("user", UserInfo.class);
representation.addAlias("usage", UsageInfo.class);
representation.addAlias("referer", RefererInfo.class);
representation.addAlias("browser", BrowserInfo.class);
representation.addAlias("search", SearchInfo.class);
representation.addAlias("responseTime", ResponseTimeInfo.class);
}
}