/*
* Copyright (C) 2009 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.exoplatform.services.jcr.impl.xml.importing;
import org.exoplatform.services.jcr.access.AccessManager;
import org.exoplatform.services.jcr.core.nodetype.NodeTypeDataManager;
import org.exoplatform.services.jcr.dataflow.ItemDataConsumer;
import org.exoplatform.services.jcr.dataflow.ItemDataKeeper;
import org.exoplatform.services.jcr.datamodel.NodeData;
import org.exoplatform.services.jcr.impl.core.LocationFactory;
import org.exoplatform.services.jcr.impl.core.RepositoryImpl;
import org.exoplatform.services.jcr.impl.core.value.ValueFactoryImpl;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.services.security.ConversationState;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.jcr.InvalidSerializedDataException;
import javax.jcr.NamespaceRegistry;
import javax.jcr.RepositoryException;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.Namespace;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
/**
* @author <a href="mailto:Sergey.Kabashnyuk@gmail.com">Sergey Kabashnyuk</a>
* @version $Id: StreamImporter.java 14100 2008-05-12 10:53:47Z gazarenkov $
*/
public class StreamImporter implements RawDataImporter
{
private final Log log = ExoLogger.getLogger("exo.jcr.component.core.StreamImporter");
private final ContentImporter importer;
private boolean namespacesRegistered = false;
private final ItemDataKeeper dataKeeper;
/**
*
*/
public StreamImporter(NodeData parent, int uuidBehavior, ItemDataKeeper dataKeeper, ItemDataConsumer dataConsumer,
NodeTypeDataManager ntManager, LocationFactory locationFactory, ValueFactoryImpl valueFactory,
NamespaceRegistry namespaceRegistry, AccessManager accessManager, ConversationState userState,
Map<String, Object> context, RepositoryImpl repository, String currentWorkspaceName)
{
super();
this.dataKeeper = dataKeeper;
this.importer =
createContentImporter(parent, uuidBehavior, dataConsumer, ntManager, locationFactory, valueFactory,
namespaceRegistry, accessManager, userState, context, repository, currentWorkspaceName);
}
/**
* {@inheritDoc}
*/
public ContentImporter createContentImporter(NodeData parent, int uuidBehavior, ItemDataConsumer dataConsumer,
NodeTypeDataManager ntManager, LocationFactory locationFactory, ValueFactoryImpl valueFactory,
NamespaceRegistry namespaceRegistry, AccessManager accessManager, ConversationState userState,
Map<String, Object> context, RepositoryImpl repository, String currentWorkspaceName)
{
return new NeutralImporter(parent, parent.getQPath(), uuidBehavior, dataConsumer, ntManager, locationFactory,
valueFactory, namespaceRegistry, accessManager, userState, context, repository, currentWorkspaceName);
}
/**
* @param stream
* @throws RepositoryException
*/
public void importStream(InputStream stream) throws RepositoryException
{
try
{
XMLInputFactory factory = XMLInputFactory.newInstance();
//needed to avoid XXE Attacks
factory.setProperty("javax.xml.stream.isSupportingExternalEntities",false);
if (log.isDebugEnabled())
log.debug("FACTORY: " + factory);
XMLEventReader reader = factory.createXMLEventReader(stream);
if (log.isDebugEnabled())
log.debug("Start event handling");
while (reader.hasNext())
{
XMLEvent event = reader.nextEvent();
// log.info(event.toString());
switch (event.getEventType())
{
case XMLStreamConstants.START_ELEMENT :
StartElement element = event.asStartElement();
if (!namespacesRegistered)
{
namespacesRegistered = true;
registerNamespaces(element);
}
Iterator attributes = element.getAttributes();
Map<String, String> attr = new HashMap<String, String>();
while (attributes.hasNext())
{
Attribute attribute = (Attribute)attributes.next();
attr.put(attribute.getName().getPrefix() + ":" + attribute.getName().getLocalPart(), attribute
.getValue());
}
QName name = element.getName();
importer.startElement(name.getNamespaceURI(), name.getLocalPart(), name.getPrefix() + ":"
+ name.getLocalPart(), attr);
break;
case XMLStreamConstants.END_ELEMENT :
EndElement endElement = event.asEndElement();
importer.endElement(endElement.getName().getNamespaceURI(), endElement.getName().getLocalPart(),
endElement.getName().getPrefix() + ":" + endElement.getName().getLocalPart());
break;
case XMLStreamConstants.PROCESSING_INSTRUCTION :
break;
case XMLStreamConstants.CHARACTERS :
String chars = event.asCharacters().getData();
importer.characters(chars.toCharArray(), 0, chars.length());
break;
case XMLStreamConstants.COMMENT :
break;
case XMLStreamConstants.START_DOCUMENT :
break;
case XMLStreamConstants.END_DOCUMENT :
dataKeeper.save(importer.getChanges());
break;
case XMLStreamConstants.ENTITY_REFERENCE :
break;
case XMLStreamConstants.ATTRIBUTE :
break;
case XMLStreamConstants.DTD :
break;
case XMLStreamConstants.CDATA :
break;
case XMLStreamConstants.SPACE :
break;
default :
break;
}
}
if (log.isDebugEnabled())
log.debug("Event handling finished");
}
catch (XMLStreamException e)
{
throw new InvalidSerializedDataException("ImportXML failed", e);
}
}
/**
* @param event
*/
private void registerNamespaces(StartElement event)
{
Iterator<Namespace> iter = event.getNamespaces();
while (iter.hasNext())
{
Namespace namespace = iter.next();
importer.registerNamespace(namespace.getPrefix(), namespace.getNamespaceURI());
}
}
}