http://git-wip-us.apache.org/repos/asf/cayenne/blob/26d8434d/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/DataSourceInfoLoader_3_0_0_1.java ---------------------------------------------------------------------- diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/DataSourceInfoLoader_3_0_0_1.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/DataSourceInfoLoader_3_0_0_1.java index 594f3d4..dc52a50 100644 --- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/DataSourceInfoLoader_3_0_0_1.java +++ b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/DataSourceInfoLoader_3_0_0_1.java @@ -37,235 +37,192 @@ import org.xml.sax.InputSource; import org.xml.sax.XMLReader; /** - * A loader of XML for the {@link DataSourceInfo} object. The loader is compatible with - * project version 3.0.0.1 and earlier. + * A loader of XML for the {@link DataSourceInfo} object. The loader is + * compatible with project version 3.0.0.1 and earlier. * * @since 3.1 */ // TODO: andrus 12.13.2009 - unused yet.. will be used in upgrade manager class DataSourceInfoLoader_3_0_0_1 { - public DataSourceInfo load(Resource configurationResource) throws Exception { - - if (configurationResource == null) { - throw new NullPointerException("Null configurationResource"); - } - - DataSourceInfo dataSourceDescriptor = new DataSourceInfo(); - - XMLReader parser = Util.createXmlReader(); - - DriverHandler handler = new DriverHandler(dataSourceDescriptor, parser); - parser.setContentHandler(handler); - parser.setErrorHandler(handler); - parser.parse(new InputSource(configurationResource.getURL().openStream())); - - return dataSourceDescriptor; - } - - private static String passwordFromURL(URL url) { - InputStream inputStream = null; - String password = null; - - try { - inputStream = url.openStream(); - password = passwordFromInputStream(inputStream); - } - catch (IOException exception) { - // ignore - } - - return password; - } - - private static String passwordFromInputStream(InputStream inputStream) { - BufferedReader bufferedReader = null; - String password = null; - - try { - bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); - password = bufferedReader.readLine(); - } - catch (IOException exception) { - // ignoring... - } - finally { - try { - if (bufferedReader != null) { - bufferedReader.close(); - } - } - catch (Exception exception) { - } - - try { - inputStream.close(); - } - catch (IOException exception) { - } - } - - return password; - } - - private class DriverHandler extends SAXNestedTagHandler { - - private DataSourceInfo dataSourceDescriptor; - - DriverHandler(DataSourceInfo dataSourceDescriptor, XMLReader parser) { - super(parser, null); - this.dataSourceDescriptor = dataSourceDescriptor; - } - - @Override - protected ContentHandler createChildTagHandler( - String namespaceURI, - String localName, - String name, - Attributes attributes) { - - if (localName.equals("driver")) { - String className = attributes.getValue("", "class"); - dataSourceDescriptor.setJdbcDriver(className); - return new DriverChildrenHandler(parser, this); - } - - return super.createChildTagHandler(namespaceURI, localName, name, attributes); - } - } - - private class DriverChildrenHandler extends SAXNestedTagHandler { - - private DataSourceInfo dataSourceDescriptor; - - DriverChildrenHandler(XMLReader parser, DriverHandler parentHandler) { - super(parser, parentHandler); - this.dataSourceDescriptor = parentHandler.dataSourceDescriptor; - } - - @Override - protected ContentHandler createChildTagHandler( - String namespaceURI, - String localName, - String name, - Attributes attributes) { - - if (localName.equals("login")) { - - String encoderClass = attributes.getValue("encoderClass"); - - String encoderKey = attributes.getValue("encoderKey"); - if (encoderKey == null) { - encoderKey = attributes.getValue("encoderSalt"); - } - - String password = attributes.getValue("password"); - String passwordLocation = attributes.getValue("passwordLocation"); - String passwordSource = attributes.getValue("passwordSource"); - if (passwordSource == null) { - passwordSource = DataSourceInfo.PASSWORD_LOCATION_MODEL; - } - - String username = attributes.getValue("userName"); - - dataSourceDescriptor.setPasswordEncoderClass(encoderClass); - dataSourceDescriptor.setPasswordEncoderKey(encoderKey); - dataSourceDescriptor.setPasswordLocation(passwordLocation); - dataSourceDescriptor.setPasswordSource(passwordSource); - dataSourceDescriptor.setUserName(username); - - // Replace {} in passwordSource with encoderSalt -- useful for EXECUTABLE - // & URL options - if (encoderKey != null) { - passwordSource = passwordSource.replaceAll("\\{\\}", encoderKey); - } - - PasswordEncoding passwordEncoder = dataSourceDescriptor - .getPasswordEncoder(); - - if (passwordLocation != null) { - if (passwordLocation - .equals(DataSourceInfo.PASSWORD_LOCATION_CLASSPATH)) { - - ClassLoader classLoader = Thread - .currentThread() - .getContextClassLoader(); - URL url = classLoader.getResource(username); - if (url != null) { - password = passwordFromURL(url); - } - else { - // ignoring.. - } - } - else if (passwordLocation - .equals(DataSourceInfo.PASSWORD_LOCATION_URL)) { - try { - password = passwordFromURL(new URL(passwordSource)); - } - catch (MalformedURLException exception) { - // ignoring... - } - } - else if (passwordLocation - .equals(DataSourceInfo.PASSWORD_LOCATION_EXECUTABLE)) { - if (passwordSource != null) { - try { - Process process = Runtime.getRuntime().exec( - passwordSource); - password = passwordFromInputStream(process - .getInputStream()); - process.waitFor(); - } - catch (IOException exception) { - // ignoring... - } - catch (InterruptedException exception) { - // ignoring... - } - } - } - } - - if (password != null && passwordEncoder != null) { - dataSourceDescriptor.setPassword(passwordEncoder.decodePassword( - password, - encoderKey)); - } - } - else if (localName.equals("url")) { - dataSourceDescriptor.setDataSourceUrl(attributes.getValue("value")); - } - else if (localName.equals("connectionPool")) { - String min = attributes.getValue("min"); - if (min != null) { - try { - dataSourceDescriptor.setMinConnections(Integer.parseInt(min)); - } - catch (NumberFormatException nfex) { - throw new ConfigurationException( - "Non-numeric 'min' attribute '%s'", - nfex, - min); - } - } - - String max = attributes.getValue("max"); - if (max != null) { - try { - dataSourceDescriptor.setMaxConnections(Integer.parseInt(max)); - } - catch (NumberFormatException nfex) { - throw new ConfigurationException( - "Non-numeric 'max' attribute '%s'", - nfex, - max); - } - } - } - - return super.createChildTagHandler(namespaceURI, localName, name, attributes); - } - } + public DataSourceInfo load(Resource configurationResource) throws Exception { + + if (configurationResource == null) { + throw new NullPointerException("Null configurationResource"); + } + + DataSourceInfo dataSourceDescriptor = new DataSourceInfo(); + + XMLReader parser = Util.createXmlReader(); + + DriverHandler handler = new DriverHandler(dataSourceDescriptor, parser); + parser.setContentHandler(handler); + parser.setErrorHandler(handler); + parser.parse(new InputSource(configurationResource.getURL().openStream())); + + return dataSourceDescriptor; + } + + private static String passwordFromURL(URL url) { + InputStream inputStream = null; + String password = null; + + try { + inputStream = url.openStream(); + password = passwordFromInputStream(inputStream); + } catch (IOException exception) { + // ignore + } + + return password; + } + + private static String passwordFromInputStream(InputStream inputStream) { + String password = null; + + try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));) { + + password = bufferedReader.readLine(); + } catch (IOException exception) { + // ignoring... + } finally { + + try { + inputStream.close(); + } catch (IOException exception) { + } + } + + return password; + } + + private class DriverHandler extends SAXNestedTagHandler { + + private DataSourceInfo dataSourceDescriptor; + + DriverHandler(DataSourceInfo dataSourceDescriptor, XMLReader parser) { + super(parser, null); + this.dataSourceDescriptor = dataSourceDescriptor; + } + + @Override + protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String name, + Attributes attributes) { + + if (localName.equals("driver")) { + String className = attributes.getValue("", "class"); + dataSourceDescriptor.setJdbcDriver(className); + return new DriverChildrenHandler(parser, this); + } + + return super.createChildTagHandler(namespaceURI, localName, name, attributes); + } + } + + private class DriverChildrenHandler extends SAXNestedTagHandler { + + private DataSourceInfo dataSourceDescriptor; + + DriverChildrenHandler(XMLReader parser, DriverHandler parentHandler) { + super(parser, parentHandler); + this.dataSourceDescriptor = parentHandler.dataSourceDescriptor; + } + + @Override + protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String name, + Attributes attributes) { + + if (localName.equals("login")) { + + String encoderClass = attributes.getValue("encoderClass"); + + String encoderKey = attributes.getValue("encoderKey"); + if (encoderKey == null) { + encoderKey = attributes.getValue("encoderSalt"); + } + + String password = attributes.getValue("password"); + String passwordLocation = attributes.getValue("passwordLocation"); + String passwordSource = attributes.getValue("passwordSource"); + if (passwordSource == null) { + passwordSource = DataSourceInfo.PASSWORD_LOCATION_MODEL; + } + + String username = attributes.getValue("userName"); + + dataSourceDescriptor.setPasswordEncoderClass(encoderClass); + dataSourceDescriptor.setPasswordEncoderKey(encoderKey); + dataSourceDescriptor.setPasswordLocation(passwordLocation); + dataSourceDescriptor.setPasswordSource(passwordSource); + dataSourceDescriptor.setUserName(username); + + // Replace {} in passwordSource with encoderSalt -- useful for + // EXECUTABLE + // & URL options + if (encoderKey != null) { + passwordSource = passwordSource.replaceAll("\\{\\}", encoderKey); + } + + PasswordEncoding passwordEncoder = dataSourceDescriptor.getPasswordEncoder(); + + if (passwordLocation != null) { + if (passwordLocation.equals(DataSourceInfo.PASSWORD_LOCATION_CLASSPATH)) { + + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + URL url = classLoader.getResource(username); + if (url != null) { + password = passwordFromURL(url); + } else { + // ignoring.. + } + } else if (passwordLocation.equals(DataSourceInfo.PASSWORD_LOCATION_URL)) { + try { + password = passwordFromURL(new URL(passwordSource)); + } catch (MalformedURLException exception) { + // ignoring... + } + } else if (passwordLocation.equals(DataSourceInfo.PASSWORD_LOCATION_EXECUTABLE)) { + if (passwordSource != null) { + try { + Process process = Runtime.getRuntime().exec(passwordSource); + password = passwordFromInputStream(process.getInputStream()); + process.waitFor(); + } catch (IOException exception) { + // ignoring... + } catch (InterruptedException exception) { + // ignoring... + } + } + } + } + + if (password != null && passwordEncoder != null) { + dataSourceDescriptor.setPassword(passwordEncoder.decodePassword(password, encoderKey)); + } + } else if (localName.equals("url")) { + dataSourceDescriptor.setDataSourceUrl(attributes.getValue("value")); + } else if (localName.equals("connectionPool")) { + String min = attributes.getValue("min"); + if (min != null) { + try { + dataSourceDescriptor.setMinConnections(Integer.parseInt(min)); + } catch (NumberFormatException nfex) { + throw new ConfigurationException("Non-numeric 'min' attribute '%s'", nfex, min); + } + } + + String max = attributes.getValue("max"); + if (max != null) { + try { + dataSourceDescriptor.setMaxConnections(Integer.parseInt(max)); + } catch (NumberFormatException nfex) { + throw new ConfigurationException("Non-numeric 'max' attribute '%s'", nfex, max); + } + } + } + + return super.createChildTagHandler(namespaceURI, localName, name, attributes); + } + } }
http://git-wip-us.apache.org/repos/asf/cayenne/blob/26d8434d/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/XMLDataChannelDescriptorLoader_V3_0_0_1.java ---------------------------------------------------------------------- diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/XMLDataChannelDescriptorLoader_V3_0_0_1.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/XMLDataChannelDescriptorLoader_V3_0_0_1.java index fef935f..21de9dc 100644 --- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/XMLDataChannelDescriptorLoader_V3_0_0_1.java +++ b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/XMLDataChannelDescriptorLoader_V3_0_0_1.java @@ -18,7 +18,6 @@ ****************************************************************/ package org.apache.cayenne.project.upgrade.v6; -import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; @@ -90,10 +89,9 @@ class XMLDataChannelDescriptorLoader_V3_0_0_1 { URL configurationURL = configurationSource.getURL(); List<DataChannelDescriptor> domains = new ArrayList<DataChannelDescriptor>(); - InputStream in = null; - try { - in = configurationURL.openStream(); + try (InputStream in = configurationURL.openStream();) { + XMLReader parser = Util.createXmlReader(); DomainsHandler rootHandler = new DomainsHandler(configurationSource, domains, parser); @@ -102,14 +100,6 @@ class XMLDataChannelDescriptorLoader_V3_0_0_1 { parser.parse(new InputSource(in)); } catch (Exception e) { throw new ConfigurationException("Error loading configuration from %s", e, configurationURL); - } finally { - try { - if (in != null) { - in.close(); - } - } catch (IOException ioex) { - logger.info("failure closing input stream for " + configurationURL + ", ignoring", ioex); - } } return domains; http://git-wip-us.apache.org/repos/asf/cayenne/blob/26d8434d/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/XMLDataMapLoader_V3_0_0_1.java ---------------------------------------------------------------------- diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/XMLDataMapLoader_V3_0_0_1.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/XMLDataMapLoader_V3_0_0_1.java index 6e49410..6dc3d52 100644 --- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/XMLDataMapLoader_V3_0_0_1.java +++ b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/XMLDataMapLoader_V3_0_0_1.java @@ -18,17 +18,13 @@ ****************************************************************/ package org.apache.cayenne.project.upgrade.v6; -import java.io.IOException; import java.io.InputStream; import java.net.URL; import org.apache.cayenne.CayenneRuntimeException; -import org.apache.cayenne.configuration.XMLDataMapLoader; import org.apache.cayenne.map.DataMap; import org.apache.cayenne.map.MapLoader; import org.apache.cayenne.resource.Resource; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.xml.sax.InputSource; /** @@ -36,41 +32,20 @@ import org.xml.sax.InputSource; */ class XMLDataMapLoader_V3_0_0_1 { - private static Log logger = LogFactory.getLog(XMLDataMapLoader.class); + public DataMap load(Resource configurationResource) throws CayenneRuntimeException { - public DataMap load(Resource configurationResource) throws CayenneRuntimeException { + MapLoader mapLoader = new MapLoader(); + URL url = configurationResource.getURL(); - MapLoader mapLoader = new MapLoader(); - URL url = configurationResource.getURL(); + DataMap map; - InputStream in = null; + try (InputStream in = url.openStream();) { - DataMap map; + map = mapLoader.loadDataMap(new InputSource(in)); + } catch (Exception e) { + throw new CayenneRuntimeException("Error loading configuration from %s", e, url); + } - try { - in = url.openStream(); - - map = mapLoader.loadDataMap(new InputSource(in)); - } - catch (Exception e) { - throw new CayenneRuntimeException( - "Error loading configuration from %s", - e, - url); - } - finally { - try { - if (in != null) { - in.close(); - } - } - catch (IOException ioex) { - logger.info( - "failure closing input stream for " + url + ", ignoring", - ioex); - } - } - - return map; - } + return map; + } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/26d8434d/cayenne-server/src/main/java/org/apache/cayenne/BaseContext.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/BaseContext.java b/cayenne-server/src/main/java/org/apache/cayenne/BaseContext.java index 174d266..4d59e7a 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/BaseContext.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/BaseContext.java @@ -18,6 +18,13 @@ ****************************************************************/ package org.apache.cayenne; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + import org.apache.cayenne.cache.NestedQueryCache; import org.apache.cayenne.cache.QueryCache; import org.apache.cayenne.configuration.CayenneRuntime; @@ -43,13 +50,6 @@ import org.apache.cayenne.reflect.ToManyProperty; import org.apache.cayenne.reflect.ToOneProperty; import org.apache.cayenne.util.ObjectContextGraphAction; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - /** * A common base superclass for Cayenne ObjectContext implementors. * @@ -57,630 +57,630 @@ import java.util.concurrent.ConcurrentHashMap; */ public abstract class BaseContext implements ObjectContext { - /** - * A holder of a ObjectContext bound to the current thread. - * - * @since 3.0 - */ - protected static final ThreadLocal<ObjectContext> threadObjectContext = new ThreadLocal<ObjectContext>(); - - /** - * Returns the ObjectContext bound to the current thread. - * - * @since 3.0 - * @return the ObjectContext associated with caller thread. - * @throws IllegalStateException - * if there is no ObjectContext bound to the current thread. - */ - public static ObjectContext getThreadObjectContext() throws IllegalStateException { - ObjectContext context = threadObjectContext.get(); - if (context == null) { - throw new IllegalStateException("Current thread has no bound ObjectContext."); - } - - return context; - } - - /** - * Binds a ObjectContext to the current thread. ObjectContext can later be - * retrieved by users in the same thread by calling - * {@link BaseContext#getThreadObjectContext}. Using null parameter will - * unbind currently bound ObjectContext. - * - * @since 3.0 - */ - public static void bindThreadObjectContext(ObjectContext context) { - threadObjectContext.set(context); - } - - // transient variables that should be reinitialized on deserialization from - // the - // registry - protected transient DataChannel channel; - protected transient QueryCache queryCache; - protected transient EntityResolver entityResolver; - - protected boolean validatingObjectsOnCommit = true; - - /** - * Graph action that handles property changes - * - * @since 3.1 - */ - protected ObjectContextGraphAction graphAction; - - /** - * Stores user defined properties associated with this DataContext. - * - * @since 3.0 - */ - protected volatile Map<String, Object> userProperties; - - protected BaseContext() { - graphAction = new ObjectContextGraphAction(this); - } - - /** - * Checks whether this context is attached to Cayenne runtime stack and if - * not, attempts to attach itself to the runtime using Injector returned - * from the call to {@link CayenneRuntime#getThreadInjector()}. If thread - * Injector is not available and the context is not attached, throws - * CayenneRuntimeException. - * <p> - * This method is called internally by the context before access to - * transient variables to allow the context to attach to the stack lazily - * following deserialization. - * - * @return true if the context successfully attached to the thread runtime, - * false - if it was already attached. - * @since 3.1 - */ - protected boolean attachToRuntimeIfNeeded() { - if (channel != null) { - return false; - } - - Injector injector = CayenneRuntime.getThreadInjector(); - if (injector == null) { - throw new CayenneRuntimeException("Can't attach to Cayenne runtime. " - + "Null injector returned from CayenneRuntime.getThreadInjector()"); - } - - attachToRuntime(injector); - return true; - } - - /** - * Attaches this context to the CayenneRuntime whose Injector is passed as - * an argument to this method. - * - * @since 3.1 - */ - protected void attachToRuntime(Injector injector) { - - // TODO: nested contexts handling?? - attachToChannel(injector.getInstance(DataChannel.class)); - setQueryCache(new NestedQueryCache(injector.getInstance(QueryCache.class))); - } - - /** - * Attaches to a provided DataChannel. - * - * @since 3.1 - */ - protected void attachToChannel(DataChannel channel) { - if (channel == null) { - throw new NullPointerException("Null channel"); - } - - setChannel(channel); - setEntityResolver(channel.getEntityResolver()); - } - - @Override - public abstract void commitChanges(); - - @Override - public abstract void commitChangesToParent(); - - @Override - public void deleteObject(Object object) throws DeleteDenyException { - deleteObjects(object); - } - - @Override - public abstract Collection<?> deletedObjects(); - - @Override - public DataChannel getChannel() { - attachToRuntimeIfNeeded(); - return channel; - } - - /** - * Sets a new DataChannel for this context. - * - * @since 3.1 - */ - public void setChannel(DataChannel channel) { - this.channel = channel; - } - - @Override - public EntityResolver getEntityResolver() { - attachToRuntimeIfNeeded(); - return entityResolver; - } - - /** - * @since 3.1 - */ - public void setEntityResolver(EntityResolver entityResolver) { - this.entityResolver = entityResolver; - } - - /** - * Returns whether this ObjectContext performs object validation before - * commit is executed. - * - * @since 1.1 - */ - public boolean isValidatingObjectsOnCommit() { - return validatingObjectsOnCommit; - } - - /** - * Sets the property defining whether this ObjectContext should perform - * object validation before commit is executed. - * - * @since 1.1 - */ - public void setValidatingObjectsOnCommit(boolean flag) { - this.validatingObjectsOnCommit = flag; - } - - /** - * @since 3.1 - */ - @Override - public <T extends Persistent> T localObject(T objectFromAnotherContext) { - - if (objectFromAnotherContext == null) { - throw new NullPointerException("Null object argument"); - } - - ObjectId id = objectFromAnotherContext.getObjectId(); - - // first look for the ID in the local GraphManager - synchronized (getGraphManager()) { - T localObject = (T) getGraphManager().getNode(id); - if (localObject != null) { - return localObject; - } - - // create a hollow object, optimistically assuming that the ID we - // got from - // 'objectFromAnotherContext' is a valid ID either in the parent - // context or in - // the DB. This essentially defers possible FaultFailureExceptions. - - ClassDescriptor descriptor = getEntityResolver().getClassDescriptor(id.getEntityName()); - Persistent persistent = (Persistent) descriptor.createObject(); - - persistent.setObjectContext(this); - persistent.setObjectId(id); - persistent.setPersistenceState(PersistenceState.HOLLOW); - - getGraphManager().registerNode(id, persistent); - - return (T) persistent; - } - } - - @Override - public abstract GraphManager getGraphManager(); - - @Override - public abstract Collection<?> modifiedObjects(); - - @Override - public abstract <T> T newObject(Class<T> persistentClass); - - @Override - public abstract void registerNewObject(Object object); - - @Override - public abstract Collection<?> newObjects(); - - @Override - public abstract QueryResponse performGenericQuery(Query query); - - @Override - public abstract List performQuery(Query query); - - /** - * @since 4.0 - */ - @SuppressWarnings("unchecked") - @Override - public <T> List<T> select(Select<T> query) { - return performQuery(query); - } - - /** - * @since 4.0 - */ - @Override - public <T> T selectOne(Select<T> query) { - List<T> objects = select(query); - - if (objects.size() == 0) { - return null; - } else if (objects.size() > 1) { - throw new CayenneRuntimeException("Expected zero or one object, instead query matched: " + objects.size()); - } - - return objects.get(0); - } - - /** - * @since 4.0 - */ - @Override - public <T> T selectFirst(Select<T> query) { - List<T> objects = select(query); - - return (objects == null || objects.isEmpty()) ? null : objects.get(0); - } - - /** - * @since 4.0 - */ - @Override - public <T> void iterate(Select<T> query, ResultIteratorCallback<T> callback) { - ResultIterator<T> it = iterator(query); - try { - for(T t : it) { - callback.next(t); - } - } finally { - it.close(); - } - } - - @Override - public abstract <T> ResultIterator<T> iterator(Select<T> query); - - @Override - public <T> ResultBatchIterator<T> batchIterator(Select<T> query, int size) { - return new ResultBatchIterator<T>(iterator(query), size); - } - - @Override - public void prepareForAccess(Persistent object, String property, boolean lazyFaulting) { - if (object.getPersistenceState() == PersistenceState.HOLLOW) { - - ObjectId oid = object.getObjectId(); - List<?> objects = performQuery(new ObjectIdQuery(oid, false, ObjectIdQuery.CACHE)); - - if (objects.size() == 0) { - throw new FaultFailureException( - "Error resolving fault, no matching row exists in the database for ObjectId: " + oid); - } else if (objects.size() > 1) { - throw new FaultFailureException( - "Error resolving fault, more than one row exists in the database for ObjectId: " + oid); - } - - // 5/28/2013 - Commented out this block to allow for modifying - // objects in the postLoad callback - // sanity check... - // if (object.getPersistenceState() != PersistenceState.COMMITTED) { - // - // String state = - // PersistenceState.persistenceStateName(object.getPersistenceState()); - // - // // TODO: andrus 4/13/2006, modified and deleted states are - // // possible due to - // // a race condition, should we handle them here? - // throw new - // FaultFailureException("Error resolving fault for ObjectId: " + - // oid + " and state (" + state - // + - // "). Possible cause - matching row is missing from the database."); - // } - } - - // resolve relationship fault - if (lazyFaulting && property != null) { - ClassDescriptor classDescriptor = getEntityResolver().getClassDescriptor( - object.getObjectId().getEntityName()); - PropertyDescriptor propertyDescriptor = classDescriptor.getProperty(property); - - // If we don't have a property descriptor, there's not much we can - // do. - // Let the caller know that the specified property could not be - // found and list - // all of the properties that could be so the caller knows what can - // be used. - if (propertyDescriptor == null) { - final StringBuilder errorMessage = new StringBuilder(); - - errorMessage.append(String.format("Property '%s' is not declared for entity '%s'.", property, object - .getObjectId().getEntityName())); - - errorMessage.append(" Declared properties are: "); - - // Grab each of the declared properties. - final List<String> properties = new ArrayList<String>(); - classDescriptor.visitProperties(new PropertyVisitor() { - @Override - public boolean visitAttribute(final AttributeProperty property) { - properties.add(property.getName()); - - return true; - } - @Override - public boolean visitToOne(final ToOneProperty property) { - properties.add(property.getName()); - - return true; - } - @Override - public boolean visitToMany(final ToManyProperty property) { - properties.add(property.getName()); - - return true; - } - }); - - // Now add the declared property names to the error message. - boolean first = true; - for (String declaredProperty : properties) { - if (first) { - errorMessage.append(String.format("'%s'", declaredProperty)); - - first = false; - } else { - errorMessage.append(String.format(", '%s'", declaredProperty)); - } - } - - errorMessage.append("."); - - throw new CayenneRuntimeException(errorMessage.toString()); - } - - // this should trigger fault resolving - propertyDescriptor.readProperty(object); - } - } - - @Override - public void propertyChanged(Persistent object, String property, Object oldValue, Object newValue) { - graphAction.handlePropertyChange(object, property, oldValue, newValue); - } - - @Override - public abstract void rollbackChanges(); - - @Override - public abstract void rollbackChangesLocally(); - - @Override - public abstract Collection<?> uncommittedObjects(); - - public QueryCache getQueryCache() { - attachToRuntimeIfNeeded(); - return queryCache; - } - - /** - * Sets a QueryCache to be used for storing cached query results. - */ - public void setQueryCache(QueryCache queryCache) { - this.queryCache = queryCache; - } - - /** - * Returns EventManager associated with the ObjectStore. - * - * @since 1.2 - */ - @Override - public EventManager getEventManager() { - return channel != null ? channel.getEventManager() : null; - } - - @Override - public GraphDiff onSync(ObjectContext originatingContext, GraphDiff changes, int syncType) { - switch (syncType) { - case DataChannel.ROLLBACK_CASCADE_SYNC: - return onContextRollback(originatingContext); - case DataChannel.FLUSH_NOCASCADE_SYNC: - return onContextFlush(originatingContext, changes, false); - case DataChannel.FLUSH_CASCADE_SYNC: - return onContextFlush(originatingContext, changes, true); - default: - throw new CayenneRuntimeException("Unrecognized SyncMessage type: " + syncType); - } - } - - GraphDiff onContextRollback(ObjectContext originatingContext) { - rollbackChanges(); - return new CompoundDiff(); - } - - protected abstract GraphDiff onContextFlush(ObjectContext originatingContext, GraphDiff changes, boolean cascade); - - /** - * @since 1.2 - */ - protected void fireDataChannelCommitted(Object postedBy, GraphDiff changes) { - EventManager manager = getEventManager(); - - if (manager != null) { - GraphEvent e = new GraphEvent(this, postedBy, changes); - manager.postEvent(e, DataChannel.GRAPH_FLUSHED_SUBJECT); - } - } - - /** - * @since 1.2 - */ - protected void fireDataChannelRolledback(Object postedBy, GraphDiff changes) { - EventManager manager = getEventManager(); - - if (manager != null) { - GraphEvent e = new GraphEvent(this, postedBy, changes); - manager.postEvent(e, DataChannel.GRAPH_ROLLEDBACK_SUBJECT); - } - } - - /** - * @since 1.2 - */ - protected void fireDataChannelChanged(Object postedBy, GraphDiff changes) { - EventManager manager = getEventManager(); - - if (manager != null) { - GraphEvent e = new GraphEvent(this, postedBy, changes); - manager.postEvent(e, DataChannel.GRAPH_CHANGED_SUBJECT); - } - } - - @Override - public void invalidateObjects(Collection<?> objects) { - - // don't allow null collections as a matter of coding discipline - if (objects == null) { - throw new NullPointerException("Null collection of objects to invalidate"); - } - - if (!objects.isEmpty()) { - performGenericQuery(new RefreshQuery(objects)); - } - } - - /** - * @since 3.1 - */ - @Override - public <T> void invalidateObjects(T... objects) { - if (objects != null && objects.length > 0) { - performGenericQuery(new RefreshQuery(Arrays.asList(objects))); - } - } - - /** - * Returns a map of user-defined properties associated with this - * DataContext. - * - * @since 3.0 - */ - protected Map<String, Object> getUserProperties() { - - // as not all users will take advantage of properties, creating the - // map on demand to keep the context lean... - if (userProperties == null) { - synchronized (this) { - if (userProperties == null) { - userProperties = new ConcurrentHashMap<String, Object>(); - } - } - } - - return userProperties; - } - - /** - * Returns a user-defined property previously set via 'setUserProperty'. - * Note that it is a caller responsibility to synchronize access to - * properties. - * - * @since 3.0 - */ - @Override - public Object getUserProperty(String key) { - return getUserProperties().get(key); - } - - /** - * Sets a user-defined property. Note that it is a caller responsibility to - * synchronize access to properties. - * - * @since 3.0 - */ - @Override - public void setUserProperty(String key, Object value) { - getUserProperties().put(key, value); - } - - /** - * If ObjEntity qualifier is set, asks it to inject initial value to an - * object. Also performs all Persistent initialization operations - */ - protected void injectInitialValue(Object obj) { - // must follow this exact order of property initialization per CAY-653, - // i.e. have - // the id and the context in place BEFORE setPersistence is called - - Persistent object = (Persistent) obj; - - object.setObjectContext(this); - object.setPersistenceState(PersistenceState.NEW); - - GraphManager graphManager = getGraphManager(); - synchronized (graphManager) { - graphManager.registerNode(object.getObjectId(), object); - graphManager.nodeCreated(object.getObjectId()); - } - - ObjEntity entity; - try { - entity = getEntityResolver().getObjEntity(object.getClass()); - } catch (CayenneRuntimeException ex) { - // ObjEntity cannot be fetched, ignored - entity = null; - } - - if (entity != null) { - if (entity.getDeclaredQualifier() instanceof ValueInjector) { - ((ValueInjector) entity.getDeclaredQualifier()).injectValue(object); - } - } - - // invoke callbacks - getEntityResolver().getCallbackRegistry().performCallbacks(LifecycleEvent.POST_ADD, object); - } - - /** - * @since 3.1 - */ - @Override - public <T> void deleteObjects(T... objects) throws DeleteDenyException { - if (objects == null || objects.length == 0) { - return; - } - - ObjectContextDeleteAction action = new ObjectContextDeleteAction(this); - - for (Object object : objects) { - action.performDelete((Persistent) object); - } - } - - @Override - public void deleteObjects(Collection<?> objects) throws DeleteDenyException { - if (objects.isEmpty()) { - return; - } - - ObjectContextDeleteAction action = new ObjectContextDeleteAction(this); - - // Make a copy to iterate over to avoid ConcurrentModificationException. - List<Object> copy = new ArrayList<Object>(objects); - for (Object object : copy) { - action.performDelete((Persistent) object); - } - } + /** + * A holder of a ObjectContext bound to the current thread. + * + * @since 3.0 + */ + protected static final ThreadLocal<ObjectContext> threadObjectContext = new ThreadLocal<ObjectContext>(); + + /** + * Returns the ObjectContext bound to the current thread. + * + * @since 3.0 + * @return the ObjectContext associated with caller thread. + * @throws IllegalStateException + * if there is no ObjectContext bound to the current thread. + */ + public static ObjectContext getThreadObjectContext() throws IllegalStateException { + ObjectContext context = threadObjectContext.get(); + if (context == null) { + throw new IllegalStateException("Current thread has no bound ObjectContext."); + } + + return context; + } + + /** + * Binds a ObjectContext to the current thread. ObjectContext can later be + * retrieved by users in the same thread by calling + * {@link BaseContext#getThreadObjectContext}. Using null parameter will + * unbind currently bound ObjectContext. + * + * @since 3.0 + */ + public static void bindThreadObjectContext(ObjectContext context) { + threadObjectContext.set(context); + } + + // transient variables that should be reinitialized on deserialization from + // the + // registry + protected transient DataChannel channel; + protected transient QueryCache queryCache; + protected transient EntityResolver entityResolver; + + protected boolean validatingObjectsOnCommit = true; + + /** + * Graph action that handles property changes + * + * @since 3.1 + */ + protected ObjectContextGraphAction graphAction; + + /** + * Stores user defined properties associated with this DataContext. + * + * @since 3.0 + */ + protected volatile Map<String, Object> userProperties; + + protected BaseContext() { + graphAction = new ObjectContextGraphAction(this); + } + + /** + * Checks whether this context is attached to Cayenne runtime stack and if + * not, attempts to attach itself to the runtime using Injector returned + * from the call to {@link CayenneRuntime#getThreadInjector()}. If thread + * Injector is not available and the context is not attached, throws + * CayenneRuntimeException. + * <p> + * This method is called internally by the context before access to + * transient variables to allow the context to attach to the stack lazily + * following deserialization. + * + * @return true if the context successfully attached to the thread runtime, + * false - if it was already attached. + * @since 3.1 + */ + protected boolean attachToRuntimeIfNeeded() { + if (channel != null) { + return false; + } + + Injector injector = CayenneRuntime.getThreadInjector(); + if (injector == null) { + throw new CayenneRuntimeException("Can't attach to Cayenne runtime. " + + "Null injector returned from CayenneRuntime.getThreadInjector()"); + } + + attachToRuntime(injector); + return true; + } + + /** + * Attaches this context to the CayenneRuntime whose Injector is passed as + * an argument to this method. + * + * @since 3.1 + */ + protected void attachToRuntime(Injector injector) { + + // TODO: nested contexts handling?? + attachToChannel(injector.getInstance(DataChannel.class)); + setQueryCache(new NestedQueryCache(injector.getInstance(QueryCache.class))); + } + + /** + * Attaches to a provided DataChannel. + * + * @since 3.1 + */ + protected void attachToChannel(DataChannel channel) { + if (channel == null) { + throw new NullPointerException("Null channel"); + } + + setChannel(channel); + setEntityResolver(channel.getEntityResolver()); + } + + @Override + public abstract void commitChanges(); + + @Override + public abstract void commitChangesToParent(); + + @Override + public void deleteObject(Object object) throws DeleteDenyException { + deleteObjects(object); + } + + @Override + public abstract Collection<?> deletedObjects(); + + @Override + public DataChannel getChannel() { + attachToRuntimeIfNeeded(); + return channel; + } + + /** + * Sets a new DataChannel for this context. + * + * @since 3.1 + */ + public void setChannel(DataChannel channel) { + this.channel = channel; + } + + @Override + public EntityResolver getEntityResolver() { + attachToRuntimeIfNeeded(); + return entityResolver; + } + + /** + * @since 3.1 + */ + public void setEntityResolver(EntityResolver entityResolver) { + this.entityResolver = entityResolver; + } + + /** + * Returns whether this ObjectContext performs object validation before + * commit is executed. + * + * @since 1.1 + */ + public boolean isValidatingObjectsOnCommit() { + return validatingObjectsOnCommit; + } + + /** + * Sets the property defining whether this ObjectContext should perform + * object validation before commit is executed. + * + * @since 1.1 + */ + public void setValidatingObjectsOnCommit(boolean flag) { + this.validatingObjectsOnCommit = flag; + } + + /** + * @since 3.1 + */ + @Override + public <T extends Persistent> T localObject(T objectFromAnotherContext) { + + if (objectFromAnotherContext == null) { + throw new NullPointerException("Null object argument"); + } + + ObjectId id = objectFromAnotherContext.getObjectId(); + + // first look for the ID in the local GraphManager + synchronized (getGraphManager()) { + T localObject = (T) getGraphManager().getNode(id); + if (localObject != null) { + return localObject; + } + + // create a hollow object, optimistically assuming that the ID we + // got from + // 'objectFromAnotherContext' is a valid ID either in the parent + // context or in + // the DB. This essentially defers possible FaultFailureExceptions. + + ClassDescriptor descriptor = getEntityResolver().getClassDescriptor(id.getEntityName()); + Persistent persistent = (Persistent) descriptor.createObject(); + + persistent.setObjectContext(this); + persistent.setObjectId(id); + persistent.setPersistenceState(PersistenceState.HOLLOW); + + getGraphManager().registerNode(id, persistent); + + return (T) persistent; + } + } + + @Override + public abstract GraphManager getGraphManager(); + + @Override + public abstract Collection<?> modifiedObjects(); + + @Override + public abstract <T> T newObject(Class<T> persistentClass); + + @Override + public abstract void registerNewObject(Object object); + + @Override + public abstract Collection<?> newObjects(); + + @Override + public abstract QueryResponse performGenericQuery(Query query); + + @Override + public abstract List performQuery(Query query); + + /** + * @since 4.0 + */ + @SuppressWarnings("unchecked") + @Override + public <T> List<T> select(Select<T> query) { + return performQuery(query); + } + + /** + * @since 4.0 + */ + @Override + public <T> T selectOne(Select<T> query) { + List<T> objects = select(query); + + if (objects.size() == 0) { + return null; + } else if (objects.size() > 1) { + throw new CayenneRuntimeException("Expected zero or one object, instead query matched: " + objects.size()); + } + + return objects.get(0); + } + + /** + * @since 4.0 + */ + @Override + public <T> T selectFirst(Select<T> query) { + List<T> objects = select(query); + + return (objects == null || objects.isEmpty()) ? null : objects.get(0); + } + + /** + * @since 4.0 + */ + @Override + public <T> void iterate(Select<T> query, ResultIteratorCallback<T> callback) { + + try (ResultIterator<T> it = iterator(query);) { + for (T t : it) { + callback.next(t); + } + } + } + + @Override + public abstract <T> ResultIterator<T> iterator(Select<T> query); + + @Override + public <T> ResultBatchIterator<T> batchIterator(Select<T> query, int size) { + return new ResultBatchIterator<T>(iterator(query), size); + } + + @Override + public void prepareForAccess(Persistent object, String property, boolean lazyFaulting) { + if (object.getPersistenceState() == PersistenceState.HOLLOW) { + + ObjectId oid = object.getObjectId(); + List<?> objects = performQuery(new ObjectIdQuery(oid, false, ObjectIdQuery.CACHE)); + + if (objects.size() == 0) { + throw new FaultFailureException( + "Error resolving fault, no matching row exists in the database for ObjectId: " + oid); + } else if (objects.size() > 1) { + throw new FaultFailureException( + "Error resolving fault, more than one row exists in the database for ObjectId: " + oid); + } + + // 5/28/2013 - Commented out this block to allow for modifying + // objects in the postLoad callback + // sanity check... + // if (object.getPersistenceState() != PersistenceState.COMMITTED) { + // + // String state = + // PersistenceState.persistenceStateName(object.getPersistenceState()); + // + // // TODO: andrus 4/13/2006, modified and deleted states are + // // possible due to + // // a race condition, should we handle them here? + // throw new + // FaultFailureException("Error resolving fault for ObjectId: " + + // oid + " and state (" + state + // + + // "). Possible cause - matching row is missing from the database."); + // } + } + + // resolve relationship fault + if (lazyFaulting && property != null) { + ClassDescriptor classDescriptor = getEntityResolver().getClassDescriptor( + object.getObjectId().getEntityName()); + PropertyDescriptor propertyDescriptor = classDescriptor.getProperty(property); + + // If we don't have a property descriptor, there's not much we can + // do. + // Let the caller know that the specified property could not be + // found and list + // all of the properties that could be so the caller knows what can + // be used. + if (propertyDescriptor == null) { + final StringBuilder errorMessage = new StringBuilder(); + + errorMessage.append(String.format("Property '%s' is not declared for entity '%s'.", property, object + .getObjectId().getEntityName())); + + errorMessage.append(" Declared properties are: "); + + // Grab each of the declared properties. + final List<String> properties = new ArrayList<String>(); + classDescriptor.visitProperties(new PropertyVisitor() { + @Override + public boolean visitAttribute(final AttributeProperty property) { + properties.add(property.getName()); + + return true; + } + + @Override + public boolean visitToOne(final ToOneProperty property) { + properties.add(property.getName()); + + return true; + } + + @Override + public boolean visitToMany(final ToManyProperty property) { + properties.add(property.getName()); + + return true; + } + }); + + // Now add the declared property names to the error message. + boolean first = true; + for (String declaredProperty : properties) { + if (first) { + errorMessage.append(String.format("'%s'", declaredProperty)); + + first = false; + } else { + errorMessage.append(String.format(", '%s'", declaredProperty)); + } + } + + errorMessage.append("."); + + throw new CayenneRuntimeException(errorMessage.toString()); + } + + // this should trigger fault resolving + propertyDescriptor.readProperty(object); + } + } + + @Override + public void propertyChanged(Persistent object, String property, Object oldValue, Object newValue) { + graphAction.handlePropertyChange(object, property, oldValue, newValue); + } + + @Override + public abstract void rollbackChanges(); + + @Override + public abstract void rollbackChangesLocally(); + + @Override + public abstract Collection<?> uncommittedObjects(); + + public QueryCache getQueryCache() { + attachToRuntimeIfNeeded(); + return queryCache; + } + + /** + * Sets a QueryCache to be used for storing cached query results. + */ + public void setQueryCache(QueryCache queryCache) { + this.queryCache = queryCache; + } + + /** + * Returns EventManager associated with the ObjectStore. + * + * @since 1.2 + */ + @Override + public EventManager getEventManager() { + return channel != null ? channel.getEventManager() : null; + } + + @Override + public GraphDiff onSync(ObjectContext originatingContext, GraphDiff changes, int syncType) { + switch (syncType) { + case DataChannel.ROLLBACK_CASCADE_SYNC: + return onContextRollback(originatingContext); + case DataChannel.FLUSH_NOCASCADE_SYNC: + return onContextFlush(originatingContext, changes, false); + case DataChannel.FLUSH_CASCADE_SYNC: + return onContextFlush(originatingContext, changes, true); + default: + throw new CayenneRuntimeException("Unrecognized SyncMessage type: " + syncType); + } + } + + GraphDiff onContextRollback(ObjectContext originatingContext) { + rollbackChanges(); + return new CompoundDiff(); + } + + protected abstract GraphDiff onContextFlush(ObjectContext originatingContext, GraphDiff changes, boolean cascade); + + /** + * @since 1.2 + */ + protected void fireDataChannelCommitted(Object postedBy, GraphDiff changes) { + EventManager manager = getEventManager(); + + if (manager != null) { + GraphEvent e = new GraphEvent(this, postedBy, changes); + manager.postEvent(e, DataChannel.GRAPH_FLUSHED_SUBJECT); + } + } + + /** + * @since 1.2 + */ + protected void fireDataChannelRolledback(Object postedBy, GraphDiff changes) { + EventManager manager = getEventManager(); + + if (manager != null) { + GraphEvent e = new GraphEvent(this, postedBy, changes); + manager.postEvent(e, DataChannel.GRAPH_ROLLEDBACK_SUBJECT); + } + } + + /** + * @since 1.2 + */ + protected void fireDataChannelChanged(Object postedBy, GraphDiff changes) { + EventManager manager = getEventManager(); + + if (manager != null) { + GraphEvent e = new GraphEvent(this, postedBy, changes); + manager.postEvent(e, DataChannel.GRAPH_CHANGED_SUBJECT); + } + } + + @Override + public void invalidateObjects(Collection<?> objects) { + + // don't allow null collections as a matter of coding discipline + if (objects == null) { + throw new NullPointerException("Null collection of objects to invalidate"); + } + + if (!objects.isEmpty()) { + performGenericQuery(new RefreshQuery(objects)); + } + } + + /** + * @since 3.1 + */ + @Override + public <T> void invalidateObjects(T... objects) { + if (objects != null && objects.length > 0) { + performGenericQuery(new RefreshQuery(Arrays.asList(objects))); + } + } + + /** + * Returns a map of user-defined properties associated with this + * DataContext. + * + * @since 3.0 + */ + protected Map<String, Object> getUserProperties() { + + // as not all users will take advantage of properties, creating the + // map on demand to keep the context lean... + if (userProperties == null) { + synchronized (this) { + if (userProperties == null) { + userProperties = new ConcurrentHashMap<String, Object>(); + } + } + } + + return userProperties; + } + + /** + * Returns a user-defined property previously set via 'setUserProperty'. + * Note that it is a caller responsibility to synchronize access to + * properties. + * + * @since 3.0 + */ + @Override + public Object getUserProperty(String key) { + return getUserProperties().get(key); + } + + /** + * Sets a user-defined property. Note that it is a caller responsibility to + * synchronize access to properties. + * + * @since 3.0 + */ + @Override + public void setUserProperty(String key, Object value) { + getUserProperties().put(key, value); + } + + /** + * If ObjEntity qualifier is set, asks it to inject initial value to an + * object. Also performs all Persistent initialization operations + */ + protected void injectInitialValue(Object obj) { + // must follow this exact order of property initialization per CAY-653, + // i.e. have + // the id and the context in place BEFORE setPersistence is called + + Persistent object = (Persistent) obj; + + object.setObjectContext(this); + object.setPersistenceState(PersistenceState.NEW); + + GraphManager graphManager = getGraphManager(); + synchronized (graphManager) { + graphManager.registerNode(object.getObjectId(), object); + graphManager.nodeCreated(object.getObjectId()); + } + + ObjEntity entity; + try { + entity = getEntityResolver().getObjEntity(object.getClass()); + } catch (CayenneRuntimeException ex) { + // ObjEntity cannot be fetched, ignored + entity = null; + } + + if (entity != null) { + if (entity.getDeclaredQualifier() instanceof ValueInjector) { + ((ValueInjector) entity.getDeclaredQualifier()).injectValue(object); + } + } + + // invoke callbacks + getEntityResolver().getCallbackRegistry().performCallbacks(LifecycleEvent.POST_ADD, object); + } + + /** + * @since 3.1 + */ + @Override + public <T> void deleteObjects(T... objects) throws DeleteDenyException { + if (objects == null || objects.length == 0) { + return; + } + + ObjectContextDeleteAction action = new ObjectContextDeleteAction(this); + + for (Object object : objects) { + action.performDelete((Persistent) object); + } + } + + @Override + public void deleteObjects(Collection<?> objects) throws DeleteDenyException { + if (objects.isEmpty()) { + return; + } + + ObjectContextDeleteAction action = new ObjectContextDeleteAction(this); + + // Make a copy to iterate over to avoid ConcurrentModificationException. + List<Object> copy = new ArrayList<Object>(objects); + for (Object object : copy) { + action.performDelete((Persistent) object); + } + } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/26d8434d/cayenne-server/src/main/java/org/apache/cayenne/ResultBatchIterator.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/ResultBatchIterator.java b/cayenne-server/src/main/java/org/apache/cayenne/ResultBatchIterator.java index 118c5e5..835d2c7 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/ResultBatchIterator.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/ResultBatchIterator.java @@ -19,7 +19,6 @@ package org.apache.cayenne; -import java.io.Closeable; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -32,12 +31,12 @@ import java.util.List; * * @since 4.0 */ -public class ResultBatchIterator<T> implements Iterable<List<T>>, Iterator<List<T>>, Closeable { +public class ResultBatchIterator<T> implements Iterable<List<T>>, Iterator<List<T>>, AutoCloseable { - private final ResultIterator delegate; + private final ResultIterator<T> delegate; private final int size; - public ResultBatchIterator(ResultIterator delegate, int size) { + public ResultBatchIterator(ResultIterator<T> delegate, int size) { this.delegate = delegate; this.size = size; } http://git-wip-us.apache.org/repos/asf/cayenne/blob/26d8434d/cayenne-server/src/main/java/org/apache/cayenne/ResultIterator.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/ResultIterator.java b/cayenne-server/src/main/java/org/apache/cayenne/ResultIterator.java index 3de04f0..a5840f4 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/ResultIterator.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/ResultIterator.java @@ -19,7 +19,6 @@ package org.apache.cayenne; -import java.io.Closeable; import java.util.List; /** @@ -32,7 +31,7 @@ import java.util.List; * * @since 3.0 */ -public interface ResultIterator<T> extends Iterable<T>, Closeable { +public interface ResultIterator<T> extends Iterable<T>, AutoCloseable { /** * Returns all yet unread rows from ResultSet without closing it. http://git-wip-us.apache.org/repos/asf/cayenne/blob/26d8434d/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java b/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java index a0fce92..5ee7531 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java @@ -562,12 +562,12 @@ class DataDomainQueryAction implements QueryRouter, OperationObserver { } @Override - public void nextRows(Query q, ResultIterator it) { + public void nextRows(Query q, ResultIterator<?> it) { throw new CayenneRuntimeException("Invalid attempt to fetch a cursor."); } @Override - public void nextGeneratedRows(Query query, ResultIterator keys, ObjectId idToUpdate) { + public void nextGeneratedRows(Query query, ResultIterator<?> keys, ObjectId idToUpdate) { if (keys != null) { try { nextRows(query, keys.allRows()); http://git-wip-us.apache.org/repos/asf/cayenne/blob/26d8434d/cayenne-server/src/main/java/org/apache/cayenne/access/DataPort.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DataPort.java b/cayenne-server/src/main/java/org/apache/cayenne/access/DataPort.java index 0691124..8dbad91 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/access/DataPort.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DataPort.java @@ -150,7 +150,7 @@ public class DataPort { if (delegate != null) { query = delegate.willCleanData(this, entity, query); } - + final int[] count = new int[] { -1 }; // perform delete query @@ -205,10 +205,10 @@ public class DataPort { Query query = (delegate != null) ? delegate.willPortEntity(this, entity, select) : select; sourceNode.performQueries(Collections.singletonList(query), observer); - ResultIterator result = observer.getResultIterator(); + InsertBatchQuery insert = new InsertBatchQuery(entity, INSERT_BATCH_SIZE); - try { + try (ResultIterator<?> result = observer.getResultIterator();) { // Split insertions into the same table into batches. // This will allow to process tables of arbitrary size @@ -243,10 +243,6 @@ public class DataPort { if (delegate != null) { delegate.didPortEntity(this, entity, currentRow); } - } finally { - - // don't forget to close ResultIterator - result.close(); } } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/26d8434d/cayenne-server/src/main/java/org/apache/cayenne/access/DbGenerator.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DbGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/access/DbGenerator.java index f9558ca..b56cae0 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/access/DbGenerator.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DbGenerator.java @@ -269,9 +269,7 @@ public class DbGenerator { public void runGenerator(DataSource ds) throws Exception { this.failures = null; - Connection connection = ds.getConnection(); - - try { + try (Connection connection = ds.getConnection();) { // drop tables if (shouldDropTables) { @@ -328,8 +326,6 @@ public class DbGenerator { } new DbGeneratorPostprocessor().execute(connection, getAdapter()); - } finally { - connection.close(); } } @@ -340,9 +336,8 @@ public class DbGenerator { * @since 1.1 */ protected boolean safeExecute(Connection connection, String sql) throws SQLException { - Statement statement = connection.createStatement(); - try { + try (Statement statement = connection.createStatement();) { jdbcEventLogger.logQuery(sql, null); statement.execute(sql); return true; @@ -354,8 +349,6 @@ public class DbGenerator { failures.addFailure(new SimpleValidationFailure(sql, ex.getMessage())); jdbcEventLogger.logQueryError(ex); return false; - } finally { - statement.close(); } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/26d8434d/cayenne-server/src/main/java/org/apache/cayenne/access/DbGeneratorPostprocessor.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DbGeneratorPostprocessor.java b/cayenne-server/src/main/java/org/apache/cayenne/access/DbGeneratorPostprocessor.java index d46c9bc..cc1eb58 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/access/DbGeneratorPostprocessor.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DbGeneratorPostprocessor.java @@ -24,53 +24,47 @@ import java.sql.SQLException; import java.util.HashMap; import java.util.Map; -import org.apache.cayenne.dba.AutoAdapter; import org.apache.cayenne.dba.DbAdapter; import org.apache.cayenne.dba.hsqldb.HSQLDBAdapter; /** - * A helper class that handles postprocessing after the schema generation operation. E.g. - * some databases require a checkpoint command to be run for the schema changes to be - * flushed to disk. + * A helper class that handles postprocessing after the schema generation + * operation. E.g. some databases require a checkpoint command to be run for the + * schema changes to be flushed to disk. * */ class DbGeneratorPostprocessor { - private static final Map<String, HSQLDBPostprocessor> postprocessors; + private static final Map<String, HSQLDBPostprocessor> postprocessors; - static { - postprocessors = new HashMap<String, HSQLDBPostprocessor>(); - postprocessors.put(HSQLDBAdapter.class.getName(), new HSQLDBPostprocessor()); - } + static { + postprocessors = new HashMap<String, HSQLDBPostprocessor>(); + postprocessors.put(HSQLDBAdapter.class.getName(), new HSQLDBPostprocessor()); + } - void execute(Connection connection, DbAdapter adapter) throws SQLException { + void execute(Connection connection, DbAdapter adapter) throws SQLException { - if (adapter != null) { - Postprocessor postprocessor = postprocessors.get(adapter - .getClass() - .getName()); - if (postprocessor != null) { - postprocessor.execute(connection); - } - } - } + if (adapter != null) { + Postprocessor postprocessor = postprocessors.get(adapter.getClass().getName()); + if (postprocessor != null) { + postprocessor.execute(connection); + } + } + } - static abstract class Postprocessor { + static abstract class Postprocessor { - abstract void execute(Connection c) throws SQLException; - } + abstract void execute(Connection c) throws SQLException; + } - static class HSQLDBPostprocessor extends Postprocessor { + static class HSQLDBPostprocessor extends Postprocessor { - @Override - void execute(Connection c) throws SQLException { - PreparedStatement st = c.prepareStatement("CHECKPOINT"); - try { - st.execute(); - } - finally { - st.close(); - } - } - } + @Override + void execute(Connection c) throws SQLException { + + try (PreparedStatement st = c.prepareStatement("CHECKPOINT");) { + st.execute(); + } + } + } }
