/* * Constellation - An open source and standard compliant SDI * http://www.constellation-sdi.org * * Copyright 2014 Geomatys. * * Licensed 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 * * http://www.apache.org/licenses/LICENSE-2.0 * * 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.constellation.sos.io.filesystem; import org.apache.sis.util.logging.Logging; import org.apache.sis.xml.MarshallerPool; import org.constellation.generic.database.Automatic; import org.constellation.metadata.io.MetadataIoException; import org.constellation.sos.factory.SMLFactory; import org.constellation.sos.io.SensorWriter; import org.constellation.ws.CstlServiceException; import org.geotoolkit.sml.xml.AbstractSensorML; import org.geotoolkit.sml.xml.SensorMLMarshallerPool; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import static org.geotoolkit.ows.xml.OWSExceptionCode.NO_APPLICABLE_CODE; /** * A sensorML Writer working on a fileSystem. * * @author Guilhem Legal (Geomatys) */ public class FileSensorWriter implements SensorWriter { /** * use for debugging purpose */ protected static final Logger LOGGER = Logging.getLogger("org.constellation.sos"); /** * A JAXB unmarshaller used to unmarshall the xml generated by the XMLWriter. */ private final MarshallerPool marshallerPool; /** * The directory where the data file are stored */ private final File dataDirectory; /** * Contains the files written during a transaction. * If the transaction is aborted, all these files will be deleted. */ private List<File> uncommittedFiles; /** * The base identifier of all the sensor. */ private final String sensorIdBase; public FileSensorWriter(final Automatic configuration, final Map<String, Object> properties) throws MetadataIoException { if (configuration == null) { throw new MetadataIoException("The sensor configuration object is null", NO_APPLICABLE_CODE); } this.sensorIdBase = (String) properties.get(SMLFactory.SENSOR_ID_BASE); uncommittedFiles = new ArrayList<>(); if (configuration.getDataDirectory() == null) { throw new MetadataIoException("The sensor data directory is null", NO_APPLICABLE_CODE); } this.dataDirectory = configuration.getDataDirectory(); this.marshallerPool = SensorMLMarshallerPool.getInstance(); if (marshallerPool == null) { throw new MetadataIoException("Unable to initialize the fileSensorWriter JAXB context", NO_APPLICABLE_CODE); } } /** * {@inheritDoc} */ @Override public boolean writeSensor(String id, final AbstractSensorML sensor) throws CstlServiceException { try { final Marshaller marshaller = marshallerPool.acquireMarshaller(); id = id.replace(":", "-"); final File currentFile = new File(dataDirectory, id + ".xml"); if (!currentFile.exists()) { final boolean create = currentFile.createNewFile(); if (!create) { throw new CstlServiceException("the service was unable to create a new file:" + currentFile.getName(), NO_APPLICABLE_CODE); } } else { LOGGER.log(Level.WARNING, "we overwrite the file: {0}", currentFile.getPath()); } marshaller.marshal(sensor, currentFile); marshallerPool.recycle(marshaller); } catch (JAXBException ex) { String msg = ex.getMessage(); if (msg == null && ex.getCause() != null) { msg = ex.getCause().getMessage(); } throw new CstlServiceException("the service has throw a JAXB Exception:" + msg, ex, NO_APPLICABLE_CODE); } catch (IOException ex) { String msg = ex.getMessage(); if (msg == null && ex.getCause() != null) { msg = ex.getCause().getMessage(); } throw new CstlServiceException("the service has throw a IO Exception:" + msg, ex, NO_APPLICABLE_CODE); } return true; } /** * {@inheritDoc} */ @Override public boolean deleteSensor(String id) throws CstlServiceException { id = id.replace(":", "-"); final File currentFile = new File(dataDirectory, id + ".xml"); boolean delete = false; if (currentFile.exists()) { delete = currentFile.delete(); } else { LOGGER.log(Level.WARNING, "unable to find a file {0} to remove", currentFile.getName()); return false; } if (!delete) { throw new CstlServiceException("the service was unable to delete the file:" + currentFile.getName(), NO_APPLICABLE_CODE); } return true; } /** * {@inheritDoc} */ @Override public int replaceSensor(String id, final AbstractSensorML sensor) throws CstlServiceException { try { final Marshaller marshaller = marshallerPool.acquireMarshaller(); id = id.replace(":", "-"); final File currentFile = new File(dataDirectory, id + ".xml"); marshaller.marshal(sensor, currentFile); marshallerPool.recycle(marshaller); return 1;//AbstractMetadataWriter.REPLACED; } catch (JAXBException ex) { String msg = ex.getMessage(); if (msg == null && ex.getCause() != null) { msg = ex.getCause().getMessage(); } throw new CstlServiceException("the service has throw a JAXB Exception:" + msg, ex, NO_APPLICABLE_CODE); } } /** * {@inheritDoc} */ @Override public void startTransaction() throws CstlServiceException { uncommittedFiles = new ArrayList<>(); } /** * {@inheritDoc} */ @Override public void abortTransaction() throws CstlServiceException { for (File f: uncommittedFiles) { final boolean delete = f.delete(); if (!delete) { LOGGER.log(Level.WARNING, "unable to delete the file:{0}", f.getName()); } } uncommittedFiles = new ArrayList<>(); } /** * {@inheritDoc} */ @Override public void endTransaction() throws CstlServiceException { uncommittedFiles = new ArrayList<>(); } /** * {@inheritDoc} */ @Override public int getNewSensorId() throws CstlServiceException { int maxID = 0; if (dataDirectory != null) { for (File f : dataDirectory.listFiles()) { String id = f.getName(); id = id.substring(0, id.indexOf(".xml")); if (id.startsWith(sensorIdBase)) { id = id.substring(id.indexOf(sensorIdBase) + sensorIdBase.length()); try { final int curentID = Integer.parseInt(id); if (curentID > maxID) { maxID = curentID; } } catch (NumberFormatException ex) { throw new CstlServiceException("unable to parse the identifier:" + id, ex, NO_APPLICABLE_CODE); } } } } return maxID + 1; } /** * {@inheritDoc} */ @Override public void destroy() { if (uncommittedFiles != null) { uncommittedFiles.clear(); } } /** * {@inheritDoc} */ @Override public String getInfos() { return "Constellation Filesystem Sensor Writer 0.9"; } }