/* * Copyright (c) 2010-2016 Evolveum * * 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 com.evolveum.midpoint.prism; import com.evolveum.midpoint.prism.crypto.Protector; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.marshaller.*; import com.evolveum.midpoint.prism.lex.LexicalProcessor; import com.evolveum.midpoint.prism.lex.LexicalProcessorRegistry; import com.evolveum.midpoint.prism.lex.dom.DomLexicalProcessor; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.polystring.PolyStringNormalizer; import com.evolveum.midpoint.prism.polystring.PrismDefaultPolyStringNormalizer; import com.evolveum.midpoint.prism.schema.SchemaDefinitionFactory; import com.evolveum.midpoint.prism.schema.SchemaRegistry; import com.evolveum.midpoint.prism.schema.SchemaRegistryImpl; import com.evolveum.midpoint.prism.util.PrismMonitor; import com.evolveum.midpoint.prism.xnode.RootXNode; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.exception.SystemException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import org.jetbrains.annotations.NotNull; import org.springframework.beans.factory.annotation.Autowired; import org.w3c.dom.Element; import org.xml.sax.SAXException; import javax.xml.namespace.QName; import java.io.File; import java.io.IOException; import java.io.InputStream; /** * @author semancik * */ public class PrismContextImpl implements PrismContext { private static final Trace LOGGER = TraceManager.getTrace(PrismContextImpl.class); private static boolean allowSchemalessSerialization = true; private static boolean extraValidation = false; // TODO replace by something serious @NotNull private final SchemaRegistryImpl schemaRegistry; @NotNull private final LexicalProcessorRegistry lexicalProcessorRegistry; @NotNull private final PolyStringNormalizer defaultPolyStringNormalizer; // TODO make non-final when needed @NotNull private final PrismUnmarshaller prismUnmarshaller; @NotNull private final PrismMarshaller prismMarshaller; @NotNull private final BeanMarshaller beanMarshaller; @NotNull private final BeanUnmarshaller beanUnmarshaller; private PrismMonitor monitor = null; private SchemaDefinitionFactory definitionFactory; @Autowired // TODO is this really applied? private Protector defaultProtector; // We need to keep this because of deprecated methods and various hacks @NotNull private final JaxbDomHack jaxbDomHack; private QName defaultRelation; //region Standard overhead private PrismContextImpl(@NotNull SchemaRegistryImpl schemaRegistry) { this.schemaRegistry = schemaRegistry; schemaRegistry.setPrismContext(this); this.lexicalProcessorRegistry = new LexicalProcessorRegistry(schemaRegistry); this.prismUnmarshaller = new PrismUnmarshaller(this); PrismBeanInspector inspector = new PrismBeanInspector(this); this.beanMarshaller = new BeanMarshaller(this, inspector); this.beanUnmarshaller = new BeanUnmarshaller(this, inspector); this.prismMarshaller = new PrismMarshaller(beanMarshaller); this.jaxbDomHack = new JaxbDomHack(lexicalProcessorRegistry.domProcessor(), this); defaultPolyStringNormalizer = new PrismDefaultPolyStringNormalizer(); } public static PrismContextImpl create(@NotNull SchemaRegistryImpl schemaRegistry) { return new PrismContextImpl(schemaRegistry); } public static PrismContextImpl createEmptyContext(@NotNull SchemaRegistryImpl schemaRegistry) { return new PrismContextImpl(schemaRegistry); } @Override public void initialize() throws SchemaException, SAXException, IOException { schemaRegistry.initialize(); } public static boolean isAllowSchemalessSerialization() { return allowSchemalessSerialization; } public static void setAllowSchemalessSerialization(boolean allowSchemalessSerialization) { PrismContextImpl.allowSchemalessSerialization = allowSchemalessSerialization; } public static boolean isExtraValidation() { return extraValidation; } public static void setExtraValidation(boolean extraValidation) { PrismContextImpl.extraValidation = extraValidation; } @Override public XmlEntityResolver getEntityResolver() { return schemaRegistry.getEntityResolver(); } @NotNull @Override public SchemaRegistry getSchemaRegistry() { return schemaRegistry; } /** * WARNING! This is not really public method. It should NOT not used outside the prism implementation. */ public PrismUnmarshaller getPrismUnmarshaller() { return prismUnmarshaller; } @NotNull public PrismMarshaller getPrismMarshaller() { return prismMarshaller; } /** * WARNING! This is not really public method. It should NOT not used outside the prism implementation. */ public DomLexicalProcessor getParserDom() { return lexicalProcessorRegistry.domProcessor(); } /** * WARNING! This is not really public method. It should NOT not used outside the prism implementation. */ @NotNull public BeanMarshaller getBeanMarshaller() { return beanMarshaller; } @NotNull public BeanUnmarshaller getBeanUnmarshaller() { return beanUnmarshaller; } @NotNull @Override public JaxbDomHack getJaxbDomHack() { return jaxbDomHack; } @NotNull public SchemaDefinitionFactory getDefinitionFactory() { if (definitionFactory == null) { definitionFactory = new SchemaDefinitionFactory(); } return definitionFactory; } public void setDefinitionFactory(SchemaDefinitionFactory definitionFactory) { this.definitionFactory = definitionFactory; } @NotNull @Override public PolyStringNormalizer getDefaultPolyStringNormalizer() { return defaultPolyStringNormalizer; } private LexicalProcessor getParser(String language) { return lexicalProcessorRegistry.processorFor(language); } private LexicalProcessor getParserNotNull(String language) { LexicalProcessor lexicalProcessor = getParser(language); if (lexicalProcessor == null) { throw new SystemException("No parser for language '"+language+"'"); } return lexicalProcessor; } @Override public Protector getDefaultProtector() { return defaultProtector; } public void setDefaultProtector(Protector defaultProtector) { this.defaultProtector = defaultProtector; } @Override public PrismMonitor getMonitor() { return monitor; } @Override public void setMonitor(PrismMonitor monitor) { this.monitor = monitor; } public QName getDefaultRelation() { return defaultRelation; } public void setDefaultRelation(QName defaultRelation) { this.defaultRelation = defaultRelation; } //endregion //region Parsing @NotNull @Override public PrismParser parserFor(@NotNull File file) { return new PrismParserImplIO(new ParserFileSource(file), null, ParsingContext.createDefault(), this, null, null, null, null); } @NotNull @Override public PrismParser parserFor(@NotNull InputStream stream) { return new PrismParserImplIO(new ParserInputStreamSource(stream), null, ParsingContext.createDefault(), this, null, null, null, null); } @NotNull @Override public PrismParserNoIO parserFor(@NotNull String data) { return new PrismParserImplNoIO(new ParserStringSource(data), null, ParsingContext.createDefault(), this, null, null, null, null); } @NotNull @Override public PrismParserNoIO parserFor(@NotNull RootXNode xnode) { return new PrismParserImplNoIO(new ParserXNodeSource(xnode), null, ParsingContext.createDefault(), this, null, null, null, null); } @NotNull @Deprecated @Override public PrismParserNoIO parserFor(@NotNull Element data) { return new PrismParserImplNoIO(new ParserElementSource(data), null, ParsingContext.createDefault(), this, null, null, null, null); } //endregion //region adopt(...) methods /** * Set up the specified object with prism context instance and schema definition. */ @Override public <C extends Containerable> void adopt(PrismContainer<C> container, Class<C> declaredType) throws SchemaException { container.revive(this); getSchemaRegistry().applyDefinition(container, declaredType, false); } @Override public <C extends Containerable> void adopt(PrismContainer<C> container) throws SchemaException { adopt(container, container.getCompileTimeClass()); } @Override public void adopt(Objectable objectable) throws SchemaException { adopt(objectable.asPrismObject(), objectable.getClass()); } @Override public void adopt(Containerable containerable) throws SchemaException { containerable.asPrismContainerValue().revive(this); } @Override public void adopt(PrismContainerValue value) throws SchemaException { value.revive(this); } @Override public <T extends Objectable> void adopt(ObjectDelta<T> delta) throws SchemaException { delta.revive(this); getSchemaRegistry().applyDefinition(delta, delta.getObjectTypeClass(), false); } @Override public <C extends Containerable, O extends Objectable> void adopt(C containerable, Class<O> type, ItemPath path) throws SchemaException { PrismContainerValue<C> prismContainerValue = containerable.asPrismContainerValue(); adopt(prismContainerValue, type, path); } @Override public <C extends Containerable, O extends Objectable> void adopt(PrismContainerValue<C> prismContainerValue, Class<O> type, ItemPath path) throws SchemaException { prismContainerValue.revive(this); getSchemaRegistry().applyDefinition(prismContainerValue, type, path, false); } @Override public <C extends Containerable, O extends Objectable> void adopt(PrismContainerValue<C> prismContainerValue, QName typeName, ItemPath path) throws SchemaException { prismContainerValue.revive(this); getSchemaRegistry().applyDefinition(prismContainerValue, typeName, path, false); } //endregion //region Serializing objects, containers, atomic values (properties) @Override public <O extends Objectable> String serializeObjectToString(PrismObject<O> object, String language) throws SchemaException { return serializerFor(language).serialize(object); } @NotNull @Override public PrismSerializer<String> serializerFor(@NotNull String language) { return new PrismSerializerImpl<>(new SerializerStringTarget(this, language), null, null, null, this); } @NotNull @Override public PrismSerializer<String> xmlSerializer() { return serializerFor(LANG_XML); } @NotNull @Override public PrismSerializer<String> jsonSerializer() { return serializerFor(LANG_JSON); } @NotNull @Override public PrismSerializer<String> yamlSerializer() { return serializerFor(LANG_YAML); } @NotNull @Override public PrismSerializer<Element> domSerializer() { return new PrismSerializerImpl<>(new SerializerDomTarget(this), null, null, null, this); } @NotNull @Override public PrismSerializer<RootXNode> xnodeSerializer() { return new PrismSerializerImpl<>(new SerializerXNodeTarget(this), null, null, null, this); } @Override public boolean canSerialize(Object value) { return prismMarshaller.canSerialize(value); } //endregion @NotNull @Override public <T extends Objectable> PrismObject<T> createObject(@NotNull Class<T> clazz) throws SchemaException { PrismObjectDefinition<T> definition = schemaRegistry.findObjectDefinitionByCompileTimeClass(clazz); if (definition == null) { throw new SchemaException("Definition for prism object holding " + clazz + " couldn't be found"); } return definition.instantiate(); } @NotNull @Override public <T extends Objectable> T createObjectable(@NotNull Class<T> clazz) throws SchemaException { return createObject(clazz).asObjectable(); } @NotNull public LexicalProcessorRegistry getLexicalProcessorRegistry() { return lexicalProcessorRegistry; } }