You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2015/09/12 12:02:41 UTC
[13/17] cayenne git commit: CAY-2026 Java 7
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();
+ }
+ }
+ }
}