/*
* Copyright (c) 2015 Data Harmonisation Panel
*
* All rights reserved. This program and the accompanying materials are made
* available under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution. If not, see <http://www.gnu.org/licenses/>.
*
* Contributors:
* Data Harmonisation Panel <http://www.dhpanel.eu>
*/
package eu.esdihumboldt.hale.io.appschema.writer;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.apache.http.entity.ContentType;
import eu.esdihumboldt.hale.common.core.io.IOProviderConfigurationException;
import eu.esdihumboldt.hale.common.core.io.ProgressIndicator;
import eu.esdihumboldt.hale.common.core.io.report.IOReporter;
import eu.esdihumboldt.hale.common.core.io.supplier.LocatableOutputSupplier;
import eu.esdihumboldt.hale.io.appschema.AppSchemaIO;
import eu.esdihumboldt.hale.io.geoserver.DataStore;
import eu.esdihumboldt.hale.io.geoserver.DataStoreFile;
import eu.esdihumboldt.hale.io.geoserver.Namespace;
import eu.esdihumboldt.hale.io.geoserver.ResourceBuilder;
import eu.esdihumboldt.hale.io.geoserver.Workspace;
import eu.esdihumboldt.hale.io.geoserver.rest.DataStoreFileManager;
import eu.esdihumboldt.hale.io.geoserver.rest.DataStoreManager;
import eu.esdihumboldt.hale.io.geoserver.rest.NamespaceManager;
/**
* Uploads the generated app-schema mapping configuration to a GeoServer
* instance using its REST API.
* <p>
* The current implementation checks for the existence of namespaces/workspaces
* and does not create nor update them if they already exist. On the contrary,
* if the target app-schema datastore already exists, it is destroyed and then
* re-created.
* </p>
*
* @author Stefano Costa, GeoSolutions
*/
public class AppSchemaMappingUploader extends AbstractAppSchemaConfigurator {
private URL geoserverURL;
private String username;
private String password;
private boolean includeTargetSchema = false;
/**
* @see eu.esdihumboldt.hale.io.appschema.writer.AbstractAppSchemaConfigurator#handleMapping(eu.esdihumboldt.hale.common.core.io.ProgressIndicator,
* eu.esdihumboldt.hale.common.core.io.report.IOReporter)
*/
@Override
protected void handleMapping(ProgressIndicator progress, IOReporter reporter)
throws IOProviderConfigurationException, IOException {
LocatableOutputSupplier<? extends OutputStream> target = getTarget();
geoserverURL = target.getLocation().toURL();
username = getParameter(AppSchemaIO.PARAM_USER).as(String.class);
password = getParameter(AppSchemaIO.PARAM_PASSWORD).as(String.class);
includeTargetSchema = getIncludeSchemaParameter();
publishNamespaces();
publishAppSchemaDataStore(progress, reporter);
}
private void publishNamespaces() {
NamespaceManager nsMgr = new NamespaceManager(geoserverURL);
nsMgr.setCredentials(username, password);
// check whether main namespace/workspace exists; if not, create it
Namespace mainNs = generator.getMainNamespace();
nsMgr.setResource(mainNs);
if (!nsMgr.exists()) {
nsMgr.create();
}
// check whether secondary namespaces/workspaces exist; if not, create
// them
List<Namespace> secondaryNamespaces = generator.getSecondaryNamespaces();
for (Namespace ns : secondaryNamespaces) {
nsMgr.setResource(ns);
if (!nsMgr.exists()) {
nsMgr.create();
}
}
}
private void publishAppSchemaDataStore(ProgressIndicator progress, IOReporter reporter)
throws IOException {
Workspace ws = generator.getMainWorkspace();
// build datastore resource
DataStore dataStore = generator.getAppSchemaDataStore();
DataStoreManager dsMgr = new DataStoreManager(geoserverURL);
dsMgr.setCredentials(username, password);
dsMgr.setResource(dataStore);
dsMgr.setWorkspace(ws.name());
// remove datastore, if necessary
if (dsMgr.exists()) {
Map<String, String> deleteParams = new HashMap<String, String>();
deleteParams.put("recurse", "true");
dsMgr.delete(deleteParams);
}
// build mapping file resource
ContentType contentType = getMimeType();
byte[] content = writeContent(dataStore.name(), contentType, progress, reporter);
DataStoreFile mappingFile = ResourceBuilder
.dataStoreFile(new ByteArrayInputStream(content), contentType)
.setAttribute(DataStoreFile.EXTENSION, "appschema")
.setAttribute(DataStoreFile.DATASTORE, dataStore.name())
.setAttribute(DataStoreFile.WORKSPACE, ws.name()).build();
DataStoreFileManager dsFileMgr = new DataStoreFileManager(geoserverURL);
dsFileMgr.setCredentials(username, password);
dsFileMgr.setResource(mappingFile);
Map<String, String> updateParams = new HashMap<String, String>();
updateParams.put("configure", "all");
dsFileMgr.update(updateParams);
}
private ContentType getMimeType() {
if (generator.getGeneratedMapping().requiresMultipleFiles() || includeTargetSchema) {
return DataStoreFile.ZIP_CONTENT_TYPE;
}
else {
return DataStoreFile.DEF_CONTENT_TYPE;
}
}
private byte[] writeContent(String mappingFileName, ContentType contentType,
ProgressIndicator progress, IOReporter reporter) throws IOException {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
if (contentType.equals(DataStoreFile.ZIP_CONTENT_TYPE)) {
try (ZipOutputStream zos = new ZipOutputStream(bos)) {
if (includeTargetSchema) {
// add target schema to zip
addTargetSchemaToZip(zos, null, progress, reporter);
}
// main mapping configuration file
zos.putNextEntry(new ZipEntry(mappingFileName + ".appschema"));
generator.writeMappingConf(zos);
zos.closeEntry();
if (generator.getGeneratedMapping().requiresMultipleFiles()) {
zos.putNextEntry(new ZipEntry(AppSchemaIO.INCLUDED_TYPES_MAPPING_FILE));
generator.writeIncludedTypesMappingConf(zos);
zos.closeEntry();
}
}
}
else {
generator.writeMappingConf(bos);
}
return bos.toByteArray();
}
}
}