/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.springframework.extensions.jcr.jackrabbit.ocm; import java.io.InputStream; import java.sql.Timestamp; import java.util.Calendar; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.Map; import javax.jcr.RepositoryException; import javax.jcr.Session; import org.apache.jackrabbit.ocm.exception.JcrMappingException; import org.apache.jackrabbit.ocm.manager.ObjectContentManager; import org.apache.jackrabbit.ocm.manager.atomictypeconverter.AtomicTypeConverter; import org.apache.jackrabbit.ocm.manager.atomictypeconverter.impl.BinaryTypeConverterImpl; import org.apache.jackrabbit.ocm.manager.atomictypeconverter.impl.BooleanTypeConverterImpl; import org.apache.jackrabbit.ocm.manager.atomictypeconverter.impl.ByteArrayTypeConverterImpl; import org.apache.jackrabbit.ocm.manager.atomictypeconverter.impl.CalendarTypeConverterImpl; import org.apache.jackrabbit.ocm.manager.atomictypeconverter.impl.DoubleTypeConverterImpl; import org.apache.jackrabbit.ocm.manager.atomictypeconverter.impl.IntTypeConverterImpl; import org.apache.jackrabbit.ocm.manager.atomictypeconverter.impl.LongTypeConverterImpl; import org.apache.jackrabbit.ocm.manager.atomictypeconverter.impl.StringTypeConverterImpl; import org.apache.jackrabbit.ocm.manager.atomictypeconverter.impl.TimestampTypeConverterImpl; import org.apache.jackrabbit.ocm.manager.atomictypeconverter.impl.UtilDateTypeConverterImpl; import org.apache.jackrabbit.ocm.manager.impl.ObjectContentManagerImpl; import org.apache.jackrabbit.ocm.mapper.Mapper; import org.apache.jackrabbit.ocm.query.Query; import org.apache.jackrabbit.ocm.query.QueryManager; import org.apache.jackrabbit.ocm.query.impl.QueryManagerImpl; import org.springframework.dao.DataAccessException; import org.springframework.extensions.jcr.JcrCallback; import org.springframework.extensions.jcr.JcrSystemException; import org.springframework.extensions.jcr.JcrTemplate; import org.springframework.extensions.jcr.SessionFactory; /** * Template which adds mapping support for the Java Content Repository. * <p/> * For PersistenceManagers the template creates internally the set of default converters. * @author Costin Leau * @see org.apache.jackrabbit.ocm.manager.ObjectContentManager */ public class JcrMappingTemplate extends JcrTemplate implements JcrMappingOperations { private Mapper mapper; /** * Default constructor for JcrTemplate */ public JcrMappingTemplate() { super(); } /** * @param sessionFactory * @param mapper */ public JcrMappingTemplate(SessionFactory sessionFactory, Mapper mapper) { setSessionFactory(sessionFactory); setMapper(mapper); afterPropertiesSet(); } /** * Add rule for checking the mapper. */ public void afterPropertiesSet() { super.afterPropertiesSet(); if (mapper == null) throw new IllegalArgumentException("mapper can NOT be null"); } /** * Method for creating a query manager. It's unclear where this entity is stateless or not. * @return */ public QueryManager createQueryManager() { try { Map atomicTypeConverters = this.createDefaultConverters(this.getSession()); return new QueryManagerImpl(mapper, atomicTypeConverters, this.getSession().getValueFactory()); } catch (RepositoryException e) { throw new JcrSystemException(e); } } /** * Creates a persistence manager. It's unclear if this object is stateless/thread-safe or not. However * because it depends on session it has to be created per session and it's not per repository. * @param session * @return * @throws JcrMappingException * @throws javax.jcr.RepositoryException */ protected ObjectContentManager createPersistenceManager(Session session) throws RepositoryException, JcrMappingException { return new ObjectContentManagerImpl(session, mapper); } /** * Due to the way the actual jcr-mapping is made we have to create the converters for each session. * @param session * @return * @throws javax.jcr.RepositoryException */ protected Map createDefaultConverters(Session session) throws RepositoryException { Map<Class, AtomicTypeConverter> map = new HashMap<Class, AtomicTypeConverter>(14); map.put(String.class, new StringTypeConverterImpl()); map.put(InputStream.class, new BinaryTypeConverterImpl()); map.put(long.class, new LongTypeConverterImpl()); map.put(Long.class, new LongTypeConverterImpl()); map.put(int.class, new IntTypeConverterImpl()); map.put(Integer.class, new IntTypeConverterImpl()); map.put(double.class, new DoubleTypeConverterImpl()); map.put(Double.class, new DoubleTypeConverterImpl()); map.put(boolean.class, new BooleanTypeConverterImpl()); map.put(Boolean.class, new BooleanTypeConverterImpl()); map.put(Calendar.class, new CalendarTypeConverterImpl()); map.put(Date.class, new UtilDateTypeConverterImpl()); map.put(byte[].class, new ByteArrayTypeConverterImpl()); map.put(Timestamp.class, new TimestampTypeConverterImpl()); return map; } public <T> T execute(final JcrMappingCallback<T> action, boolean exposeNativeSession) throws DataAccessException { return execute(new JcrCallback<T>() { public T doInJcr(Session session) throws RepositoryException { try { return action.doInJcrMapping(createPersistenceManager(session)); } catch (JcrMappingException e) { throw convertMappingAccessException(e); } } }, exposeNativeSession); } public <T> T execute(JcrMappingCallback<T> callback) throws DataAccessException { return execute(callback, isExposeNativeSession()); } // ---------------- // Delegate methods // ---------------- public void insert(final java.lang.Object object) { execute(new JcrMappingCallback<Void>() { public Void doInJcrMapping(ObjectContentManager manager) throws JcrMappingException { manager.insert(object); return null; } }, true); } public void update(final java.lang.Object object) { execute(new JcrMappingCallback<Void>() { public Void doInJcrMapping(ObjectContentManager manager) throws JcrMappingException { manager.update(object); return null; } }, true); } public void remove(final java.lang.String path) { execute(new JcrMappingCallback<Void>() { public Void doInJcrMapping(ObjectContentManager manager) throws JcrMappingException { manager.remove(path); return null; } }, true); } public Object getObject(final java.lang.String path) { return execute(new JcrMappingCallback<Object>() { public Object doInJcrMapping(ObjectContentManager manager) throws JcrMappingException { return manager.getObject(path); } }, true); } public Collection getObjects(final Query query) { return execute(new JcrMappingCallback<Collection>() { public Collection doInJcrMapping(ObjectContentManager manager) throws JcrMappingException { return manager.getObjects(query); } }, true); } /** * Convert the given MappingException to an appropriate exception from the * <code>org.springframework.dao</code> hierarchy. * <p/> * Note that because we have no base specific exception we have to catch the generic Exception and * translate it into JcrSystemException. * <p/> * May be overridden in subclasses. * @param ex Exception that occured * @return the corresponding DataAccessException instance */ public DataAccessException convertMappingAccessException(Exception ex) { // repository exception if (ex instanceof RepositoryException) return super.convertJcrAccessException((RepositoryException) ex); return new JcrSystemException(ex); } /** * @return Returns the mapper. */ public Mapper getMapper() { return mapper; } /** * @param mapper The mapper to set. */ public void setMapper(Mapper mapper) { this.mapper = mapper; } }