aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Kornilov2014-07-29 05:30:52 (EDT)
committerLukas Jungmann2014-07-30 12:02:00 (EDT)
commit80d0b9553a02c77790e01497a4f4599d95d2f135 (patch)
tree5f3dd73c33214ac2a51bf103c2a149d771399ae4
parent1d9d20aaf2a46b365052253a8cdab20cb89d99fa (diff)
downloadeclipselink.runtime-80d0b9553a02c77790e01497a4f4599d95d2f135.zip
eclipselink.runtime-80d0b9553a02c77790e01497a4f4599d95d2f135.tar.gz
eclipselink.runtime-80d0b9553a02c77790e01497a4f4599d95d2f135.tar.bz2
Bug #440774: JPARS fields filtering feature implementation.
Signed-off-by: Dmitry Kornilov <dmitry.kornilov@oracle.com>
-rw-r--r--dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/jpa/rs/PersistenceContext.java2673
-rw-r--r--dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/jpa/rs/features/FeatureSet.java10
-rw-r--r--dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/jpa/rs/features/FeatureSetV2.java2
-rw-r--r--dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/jpa/rs/features/fieldsfiltering/FieldsFilteringValidator.java101
-rw-r--r--dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/jpa/rs/resources/common/AbstractEntityResource.java24
-rw-r--r--dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/jpa/rs/util/StreamingOutputMarshaller.java359
-rw-r--r--jpa/eclipselink.jpars.test/src/org/eclipse/persistence/jpars/test/AllJavaEETests.java3
-rw-r--r--jpa/eclipselink.jpars.test/src/org/eclipse/persistence/jpars/test/server/ServerFieldsFilteringTest.java154
-rw-r--r--jpa/eclipselink.jpars.test/src/org/eclipse/persistence/jpars/test/server/ServerPageableTest.java4
-rw-r--r--jpa/eclipselink.jpars.test/src/org/eclipse/persistence/jpars/test/util/RestUtils.java28
10 files changed, 1859 insertions, 1499 deletions
diff --git a/dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/jpa/rs/PersistenceContext.java b/dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/jpa/rs/PersistenceContext.java
index c444738..a36799b 100644
--- a/dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/jpa/rs/PersistenceContext.java
+++ b/dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/jpa/rs/PersistenceContext.java
@@ -1,85 +1,86 @@
-/*******************************************************************************
+/*******************************************************************************
* Copyright (c) 2011, 2014 Oracle and/or its affiliates. All rights reserved.
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
- * which accompanies this distribution.
- * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
- * and the Eclipse Distribution License is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- *
- * Contributors:
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
* dclarke/tware - initial
* Dmitry Kornilov - Pagination related changes
- ******************************************************************************/
-package org.eclipse.persistence.jpa.rs;
-
-import org.eclipse.persistence.config.PersistenceUnitProperties;
-import org.eclipse.persistence.descriptors.ClassDescriptor;
-import org.eclipse.persistence.descriptors.FetchGroupManager;
-import org.eclipse.persistence.dynamic.DynamicEntity;
-import org.eclipse.persistence.dynamic.DynamicType;
-import org.eclipse.persistence.eis.mappings.EISCompositeCollectionMapping;
-import org.eclipse.persistence.internal.helper.ConversionManager;
-import org.eclipse.persistence.internal.jpa.EJBQueryImpl;
-import org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl;
-import org.eclipse.persistence.internal.jpa.weaving.RestAdapterClassWriter;
-import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
-import org.eclipse.persistence.internal.security.PrivilegedGetDeclaredFields;
-import org.eclipse.persistence.internal.security.PrivilegedMethodInvoker;
-import org.eclipse.persistence.internal.sessions.AbstractSession;
-import org.eclipse.persistence.internal.weaving.PersistenceWeavedRest;
-import org.eclipse.persistence.internal.weaving.RelationshipInfo;
-import org.eclipse.persistence.jaxb.JAXBContext;
-import org.eclipse.persistence.jaxb.JAXBContextProperties;
-import org.eclipse.persistence.jaxb.MarshallerProperties;
-import org.eclipse.persistence.jaxb.UnmarshallerProperties;
-import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContextFactory;
-import org.eclipse.persistence.jpa.JpaHelper;
-import org.eclipse.persistence.jpa.PersistenceProvider;
-import org.eclipse.persistence.jpa.dynamic.JPADynamicHelper;
+ ******************************************************************************/
+package org.eclipse.persistence.jpa.rs;
+
+import org.eclipse.persistence.config.PersistenceUnitProperties;
+import org.eclipse.persistence.descriptors.ClassDescriptor;
+import org.eclipse.persistence.descriptors.FetchGroupManager;
+import org.eclipse.persistence.dynamic.DynamicEntity;
+import org.eclipse.persistence.dynamic.DynamicType;
+import org.eclipse.persistence.eis.mappings.EISCompositeCollectionMapping;
+import org.eclipse.persistence.internal.helper.ConversionManager;
+import org.eclipse.persistence.internal.jpa.EJBQueryImpl;
+import org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl;
+import org.eclipse.persistence.internal.jpa.weaving.RestAdapterClassWriter;
+import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
+import org.eclipse.persistence.internal.security.PrivilegedGetDeclaredFields;
+import org.eclipse.persistence.internal.security.PrivilegedMethodInvoker;
+import org.eclipse.persistence.internal.sessions.AbstractSession;
+import org.eclipse.persistence.internal.weaving.PersistenceWeavedRest;
+import org.eclipse.persistence.internal.weaving.RelationshipInfo;
+import org.eclipse.persistence.jaxb.JAXBContext;
+import org.eclipse.persistence.jaxb.JAXBContextProperties;
+import org.eclipse.persistence.jaxb.MarshallerProperties;
+import org.eclipse.persistence.jaxb.ObjectGraph;
+import org.eclipse.persistence.jaxb.UnmarshallerProperties;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContextFactory;
+import org.eclipse.persistence.jpa.JpaHelper;
+import org.eclipse.persistence.jpa.PersistenceProvider;
+import org.eclipse.persistence.jpa.dynamic.JPADynamicHelper;
import org.eclipse.persistence.jpa.rs.annotations.RestPageableQueries;
import org.eclipse.persistence.jpa.rs.annotations.RestPageableQuery;
-import org.eclipse.persistence.jpa.rs.exceptions.JPARSException;
-import org.eclipse.persistence.jpa.rs.features.FeatureSet;
+import org.eclipse.persistence.jpa.rs.exceptions.JPARSException;
+import org.eclipse.persistence.jpa.rs.features.FeatureSet;
import org.eclipse.persistence.jpa.rs.features.ServiceVersion;
-import org.eclipse.persistence.jpa.rs.util.IdHelper;
-import org.eclipse.persistence.jpa.rs.util.JPARSLogger;
-import org.eclipse.persistence.jpa.rs.util.JTATransactionWrapper;
-import org.eclipse.persistence.jpa.rs.util.PreLoginMappingAdapter;
-import org.eclipse.persistence.jpa.rs.util.ResourceLocalTransactionWrapper;
-import org.eclipse.persistence.jpa.rs.util.TransactionWrapper;
-import org.eclipse.persistence.jpa.rs.util.list.ReadAllQueryResultCollection;
-import org.eclipse.persistence.jpa.rs.util.list.ReportQueryResultCollection;
-import org.eclipse.persistence.jpa.rs.util.list.ReportQueryResultList;
-import org.eclipse.persistence.jpa.rs.util.list.ReportQueryResultListItem;
-import org.eclipse.persistence.jpa.rs.util.list.SingleResultQueryList;
-import org.eclipse.persistence.jpa.rs.util.metadatasources.DynamicXMLMetadataSource;
-import org.eclipse.persistence.jpa.rs.util.metadatasources.ErrorResponseMetadataSource;
-import org.eclipse.persistence.jpa.rs.util.metadatasources.ItemLinksMetadataSource;
-import org.eclipse.persistence.jpa.rs.util.metadatasources.JavaLangMetadataSource;
-import org.eclipse.persistence.jpa.rs.util.metadatasources.JavaMathMetadataSource;
-import org.eclipse.persistence.jpa.rs.util.metadatasources.JavaUtilMetadataSource;
-import org.eclipse.persistence.jpa.rs.util.metadatasources.LinkMetadataSource;
-import org.eclipse.persistence.jpa.rs.util.metadatasources.LinkV2MetadataSource;
-import org.eclipse.persistence.jpa.rs.util.metadatasources.ReadAllQueryResultCollectionMetadataSource;
-import org.eclipse.persistence.jpa.rs.util.metadatasources.ReportQueryResultCollectionMetadataSource;
-import org.eclipse.persistence.jpa.rs.util.metadatasources.ReportQueryResultListItemMetadataSource;
-import org.eclipse.persistence.jpa.rs.util.metadatasources.ReportQueryResultListMetadataSource;
-import org.eclipse.persistence.jpa.rs.util.metadatasources.SimpleHomogeneousListMetadataSource;
-import org.eclipse.persistence.jpa.rs.util.metadatasources.SingleResultQueryListMetadataSource;
-import org.eclipse.persistence.jpa.rs.util.xmladapters.LinkAdapter;
-import org.eclipse.persistence.jpa.rs.util.xmladapters.RelationshipLinkAdapter;
-import org.eclipse.persistence.mappings.DatabaseMapping;
-import org.eclipse.persistence.mappings.ForeignReferenceMapping;
-import org.eclipse.persistence.mappings.ObjectReferenceMapping;
-import org.eclipse.persistence.oxm.mappings.XMLInverseReferenceMapping;
-import org.eclipse.persistence.queries.DatabaseQuery;
-import org.eclipse.persistence.queries.FetchGroup;
-import org.eclipse.persistence.queries.FetchGroupTracker;
-import org.eclipse.persistence.sessions.DatabaseSession;
-import org.eclipse.persistence.sessions.Session;
-import org.eclipse.persistence.sessions.UnitOfWork;
-
+import org.eclipse.persistence.jpa.rs.util.IdHelper;
+import org.eclipse.persistence.jpa.rs.util.JPARSLogger;
+import org.eclipse.persistence.jpa.rs.util.JTATransactionWrapper;
+import org.eclipse.persistence.jpa.rs.util.PreLoginMappingAdapter;
+import org.eclipse.persistence.jpa.rs.util.ResourceLocalTransactionWrapper;
+import org.eclipse.persistence.jpa.rs.util.TransactionWrapper;
+import org.eclipse.persistence.jpa.rs.util.list.ReadAllQueryResultCollection;
+import org.eclipse.persistence.jpa.rs.util.list.ReportQueryResultCollection;
+import org.eclipse.persistence.jpa.rs.util.list.ReportQueryResultList;
+import org.eclipse.persistence.jpa.rs.util.list.ReportQueryResultListItem;
+import org.eclipse.persistence.jpa.rs.util.list.SingleResultQueryList;
+import org.eclipse.persistence.jpa.rs.util.metadatasources.DynamicXMLMetadataSource;
+import org.eclipse.persistence.jpa.rs.util.metadatasources.ErrorResponseMetadataSource;
+import org.eclipse.persistence.jpa.rs.util.metadatasources.ItemLinksMetadataSource;
+import org.eclipse.persistence.jpa.rs.util.metadatasources.JavaLangMetadataSource;
+import org.eclipse.persistence.jpa.rs.util.metadatasources.JavaMathMetadataSource;
+import org.eclipse.persistence.jpa.rs.util.metadatasources.JavaUtilMetadataSource;
+import org.eclipse.persistence.jpa.rs.util.metadatasources.LinkMetadataSource;
+import org.eclipse.persistence.jpa.rs.util.metadatasources.LinkV2MetadataSource;
+import org.eclipse.persistence.jpa.rs.util.metadatasources.ReadAllQueryResultCollectionMetadataSource;
+import org.eclipse.persistence.jpa.rs.util.metadatasources.ReportQueryResultCollectionMetadataSource;
+import org.eclipse.persistence.jpa.rs.util.metadatasources.ReportQueryResultListItemMetadataSource;
+import org.eclipse.persistence.jpa.rs.util.metadatasources.ReportQueryResultListMetadataSource;
+import org.eclipse.persistence.jpa.rs.util.metadatasources.SimpleHomogeneousListMetadataSource;
+import org.eclipse.persistence.jpa.rs.util.metadatasources.SingleResultQueryListMetadataSource;
+import org.eclipse.persistence.jpa.rs.util.xmladapters.LinkAdapter;
+import org.eclipse.persistence.jpa.rs.util.xmladapters.RelationshipLinkAdapter;
+import org.eclipse.persistence.mappings.DatabaseMapping;
+import org.eclipse.persistence.mappings.ForeignReferenceMapping;
+import org.eclipse.persistence.mappings.ObjectReferenceMapping;
+import org.eclipse.persistence.oxm.mappings.XMLInverseReferenceMapping;
+import org.eclipse.persistence.queries.DatabaseQuery;
+import org.eclipse.persistence.queries.FetchGroup;
+import org.eclipse.persistence.queries.FetchGroupTracker;
+import org.eclipse.persistence.sessions.DatabaseSession;
+import org.eclipse.persistence.sessions.Session;
+import org.eclipse.persistence.sessions.UnitOfWork;
+
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Query;
@@ -117,46 +118,46 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
-/**
- * A wrapper around the JPA and JAXB artifacts used to persist an application.
- *
- * A PersistenceContext provides the capability of using the same persistence unit in JPA to
- * to interact with a Database or other JPA-capable data source and in JAXB to interact with either
- * XML or JSON.
- *
- * A PersistenceContext can wrap either an existing persistence unit (EntityManagerFactory), or it can be used to bootstrap a
- * fully dynamic persistence unit.
- *
- * @author douglas.clarke, tom.ware
- */
-public class PersistenceContext {
- public static final String JPARS_CONTEXT = "eclipselink.jpars.context";
- public static final String CLASS_NAME = PersistenceContext.class.getName();
-
- @SuppressWarnings("rawtypes")
- protected List<XmlAdapter> adapters = null;
-
- /**
- * The name of the persistence context is used to look it up. By default it will be the
- * persistence unit name of the JPA persistence unit.
- */
- protected String name = null;
-
- /** The EntityManagerFactory used to interact using JPA **/
- protected EntityManagerFactory emf;
-
- /** The JAXBConext used to produce JSON or XML **/
- protected JAXBContext jaxbContext = null;
-
- /** The URI of the Persistence context. This is used to build Links in JSON and XML **/
- protected URI baseURI = null;
-
- protected TransactionWrapper transaction = null;
-
- private Boolean weavingEnabled = null;
-
+/**
+ * A wrapper around the JPA and JAXB artifacts used to persist an application.
+ *
+ * A PersistenceContext provides the capability of using the same persistence unit in JPA to
+ * to interact with a Database or other JPA-capable data source and in JAXB to interact with either
+ * XML or JSON.
+ *
+ * A PersistenceContext can wrap either an existing persistence unit (EntityManagerFactory), or it can be used to bootstrap a
+ * fully dynamic persistence unit.
+ *
+ * @author douglas.clarke, tom.ware
+ */
+public class PersistenceContext {
+ public static final String JPARS_CONTEXT = "eclipselink.jpars.context";
+ public static final String CLASS_NAME = PersistenceContext.class.getName();
+
+ @SuppressWarnings("rawtypes")
+ protected List<XmlAdapter> adapters = null;
+
+ /**
+ * The name of the persistence context is used to look it up. By default it will be the
+ * persistence unit name of the JPA persistence unit.
+ */
+ protected String name = null;
+
+ /** The EntityManagerFactory used to interact using JPA **/
+ protected EntityManagerFactory emf;
+
+ /** The JAXBConext used to produce JSON or XML **/
+ protected JAXBContext jaxbContext = null;
+
+ /** The URI of the Persistence context. This is used to build Links in JSON and XML **/
+ protected URI baseURI = null;
+
+ protected TransactionWrapper transaction = null;
+
+ private Boolean weavingEnabled = null;
+
private ServiceVersion version = ServiceVersion.NO_VERSION;
-
+
/**
* JPARS pageable queries map.
* Key: named query name
@@ -164,36 +165,36 @@ public class PersistenceContext {
*/
private Map<String, RestPageableQuery> pageableQueries;
- protected PersistenceContext() {
- }
-
- /**
- * Instantiates a new persistence context.
- *
- * @param emfName the emf name
- * @param emf the emf
- * @param defaultURI the default uri
- */
- public PersistenceContext(String emfName, EntityManagerFactoryImpl emf, URI defaultURI) {
- super();
- this.emf = emf;
- this.name = emfName;
+ protected PersistenceContext() {
+ }
+
+ /**
+ * Instantiates a new persistence context.
+ *
+ * @param emfName the emf name
+ * @param emf the emf
+ * @param defaultURI the default uri
+ */
+ public PersistenceContext(String emfName, EntityManagerFactoryImpl emf, URI defaultURI) {
+ super();
+ this.emf = emf;
+ this.name = emfName;
this.baseURI = defaultURI;
- if (getServerSession().hasExternalTransactionController()) {
- transaction = new JTATransactionWrapper();
- } else {
- transaction = new ResourceLocalTransactionWrapper();
- }
- try {
- this.jaxbContext = createDynamicJAXBContext(emf.getDatabaseSession());
- } catch (JAXBException jaxbe) {
- JPARSLogger.exception("exception_creating_jaxb_context", new Object[] { emfName, jaxbe.toString() }, jaxbe);
- emf.close();
- } catch (IOException e) {
- JPARSLogger.exception("exception_creating_jaxb_context", new Object[] { emfName, e.toString() }, e);
- emf.close();
- }
+ if (getServerSession().hasExternalTransactionController()) {
+ transaction = new JTATransactionWrapper();
+ } else {
+ transaction = new ResourceLocalTransactionWrapper();
+ }
+ try {
+ this.jaxbContext = createDynamicJAXBContext(emf.getDatabaseSession());
+ } catch (JAXBException jaxbe) {
+ JPARSLogger.exception("exception_creating_jaxb_context", new Object[] { emfName, jaxbe.toString() }, jaxbe);
+ emf.close();
+ } catch (IOException e) {
+ JPARSLogger.exception("exception_creating_jaxb_context", new Object[] { emfName, e.toString() }, e);
+ emf.close();
+ }
}
/**
@@ -207,1170 +208,1196 @@ public class PersistenceContext {
public PersistenceContext(String emfName, EntityManagerFactoryImpl emf, URI defaultURI, ServiceVersion version) {
this(emfName, emf, defaultURI);
this.version = version;
- }
-
- /**
- * Checks if is weaving enabled.
- *
- * @return true, if is weaving enabled
- */
- public boolean isWeavingEnabled() {
- if (this.weavingEnabled == null) {
- this.weavingEnabled = getWeavingProperty();
- }
- return this.weavingEnabled;
- }
-
- /**
+ }
+
+ /**
+ * Checks if is weaving enabled.
+ *
+ * @return true, if is weaving enabled
+ */
+ public boolean isWeavingEnabled() {
+ if (this.weavingEnabled == null) {
+ this.weavingEnabled = getWeavingProperty();
+ }
+ return this.weavingEnabled;
+ }
+
+ /**
* Gets the version as it appears in URI.
- *
+ *
* @return The version.
- */
- public String getVersion() {
+ */
+ public String getVersion() {
return version.getCode();
- }
-
- /**
- * This method is used to help construct a JAXBContext from an existing EntityManagerFactory.
- *
- * For each package in the EntityManagerFactory, a MetadataSource that is capable of building a JAXBContext
- * that creates the same mappings in JAXB is created. These MetadataSources are used to constuct the JAXContext
+ }
+
+ /**
+ * This method is used to help construct a JAXBContext from an existing EntityManagerFactory.
+ *
+ * For each package in the EntityManagerFactory, a MetadataSource that is capable of building a JAXBContext
+ * that creates the same mappings in JAXB is created. These MetadataSources are used to constuct the JAXContext
* that is used for JSON and XML translation.
- * @param metadataSources
- * @param session
- */
- protected void addDynamicXMLMetadataSources(List<Object> metadataSources, AbstractSession session) {
- Set<String> packages = new HashSet<String>();
+ * @param metadataSources
+ * @param session
+ */
+ protected void addDynamicXMLMetadataSources(List<Object> metadataSources, AbstractSession session) {
+ Set<String> packages = new HashSet<String>();
for (Class descriptorClass : session.getDescriptors().keySet()) {
- String packageName = "";
+ String packageName = "";
int lastDotIndex = descriptorClass.getName().lastIndexOf('.');
if (lastDotIndex > 0) {
packageName = descriptorClass.getName().substring(0, lastDotIndex);
- }
- if (!packages.contains(packageName)) {
- packages.add(packageName);
- }
- }
-
- for (String packageName : packages) {
- metadataSources.add(new DynamicXMLMetadataSource(session, packageName));
- }
- }
-
- /**
+ }
+ if (!packages.contains(packageName)) {
+ packages.add(packageName);
+ }
+ }
+
+ for (String packageName : packages) {
+ metadataSources.add(new DynamicXMLMetadataSource(session, packageName));
+ }
+ }
+
+ /**
* A part of the facade over the JPA API.
* Persist an entity in JPA and commit.
- * @param tenantId
- * @param entity
- * @throws Exception
- */
- public void create(Map<String, String> tenantId, Object entity) throws Exception {
- EntityManager em = getEmf().createEntityManager(tenantId);
- try {
- transaction.beginTransaction(em);
- em.persist(entity);
- transaction.commitTransaction(em);
- } catch (RollbackException ex) {
- throw ex;
- } catch (Exception ex) {
- transaction.rollbackTransaction(em);
- throw ex;
- } finally {
- em.close();
- }
- }
-
- /**
+ * @param tenantId
+ * @param entity
+ * @throws Exception
+ */
+ public void create(Map<String, String> tenantId, Object entity) throws Exception {
+ EntityManager em = getEmf().createEntityManager(tenantId);
+ try {
+ transaction.beginTransaction(em);
+ em.persist(entity);
+ transaction.commitTransaction(em);
+ } catch (RollbackException ex) {
+ throw ex;
+ } catch (Exception ex) {
+ transaction.rollbackTransaction(em);
+ throw ex;
+ } finally {
+ em.close();
+ }
+ }
+
+ /**
* Create a JAXBContext based on the EntityManagerFactory for this PersistenceContext.
- * @param session
- * @return
- */
- protected JAXBContext createDynamicJAXBContext(AbstractSession session) throws JAXBException, IOException {
- JAXBContext jaxbContext = (JAXBContext) session.getProperty(JAXBContext.class.getName());
- if (jaxbContext != null) {
- return jaxbContext;
- }
-
- Map<String, Object> properties = createJAXBProperties(session);
-
- ClassLoader cl = session.getDatasourcePlatform().getConversionManager().getLoader();
- jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(cl, properties);
-
- session.setProperty(JAXBContext.class.getName(), jaxbContext);
-
- return jaxbContext;
- }
-
- /**
+ * @param session
+ * @return
+ */
+ protected JAXBContext createDynamicJAXBContext(AbstractSession session) throws JAXBException, IOException {
+ JAXBContext jaxbContext = (JAXBContext) session.getProperty(JAXBContext.class.getName());
+ if (jaxbContext != null) {
+ return jaxbContext;
+ }
+
+ Map<String, Object> properties = createJAXBProperties(session);
+
+ ClassLoader cl = session.getDatasourcePlatform().getConversionManager().getLoader();
+ jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(cl, properties);
+
+ session.setProperty(JAXBContext.class.getName(), jaxbContext);
+
+ return jaxbContext;
+ }
+
+ /**
* A part of the facade over the JPA API.
* Create an EntityManagerFactory using the given PersistenceUnitInfo and properties.
- * @param info
- * @param properties
- * @return
- */
- protected EntityManagerFactoryImpl createEntityManagerFactory(PersistenceUnitInfo info, Map<String, ?> properties) {
- PersistenceProvider provider = new PersistenceProvider();
- EntityManagerFactory emf = provider.createContainerEntityManagerFactory(info, properties);
- return (EntityManagerFactoryImpl) emf;
- }
-
- /**
- * A part of the facade over the JPA API
- * Create an EntityManager from the EntityManagerFactory wrapped by this persistence context
- * @param tenantId
- * @return
- */
- protected EntityManager createEntityManager(String tenantId) {
- return getEmf().createEntityManager();
- }
-
- /**
- * Build the set of properties used to create the JAXBContext based on the EntityManagerFactory that
- * this PersistenceContext wraps
- * @param session
- * @return
- * @throws IOException
- */
- @SuppressWarnings({ "unchecked", "rawtypes" })
- protected Map<String, Object> createJAXBProperties(AbstractSession session) throws IOException {
- Map<String, Object> properties = new HashMap<String, Object>(1);
- List<Object> metadataLocations = new ArrayList<Object>();
-
- addDynamicXMLMetadataSources(metadataLocations, session);
- String oxmLocation = (String) emf.getProperties().get("eclipselink.jpa-rs.oxm");
-
- if (oxmLocation != null) {
- metadataLocations.add(oxmLocation);
- }
-
- Object passedOXMLocations = emf.getProperties().get(JAXBContextProperties.OXM_METADATA_SOURCE);
- if (passedOXMLocations != null) {
- if (passedOXMLocations instanceof Collection) {
- metadataLocations.addAll((Collection) passedOXMLocations);
- } else {
- metadataLocations.add(passedOXMLocations);
- }
- }
-
- metadataLocations.add(new LinkMetadataSource());
- metadataLocations.add(new ReportQueryResultListMetadataSource());
- metadataLocations.add(new ReportQueryResultListItemMetadataSource());
- metadataLocations.add(new SingleResultQueryListMetadataSource());
- metadataLocations.add(new SimpleHomogeneousListMetadataSource());
- metadataLocations.add(new ReportQueryResultCollectionMetadataSource());
- metadataLocations.add(new ReadAllQueryResultCollectionMetadataSource());
-
- metadataLocations.add(new JavaLangMetadataSource());
- metadataLocations.add(new JavaMathMetadataSource());
- metadataLocations.add(new JavaUtilMetadataSource());
- metadataLocations.add(new LinkV2MetadataSource());
- metadataLocations.add(new ItemLinksMetadataSource());
- metadataLocations.add(new ErrorResponseMetadataSource());
-
- properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, metadataLocations);
+ * @param info
+ * @param properties
+ * @return
+ */
+ protected EntityManagerFactoryImpl createEntityManagerFactory(PersistenceUnitInfo info, Map<String, ?> properties) {
+ PersistenceProvider provider = new PersistenceProvider();
+ EntityManagerFactory emf = provider.createContainerEntityManagerFactory(info, properties);
+ return (EntityManagerFactoryImpl) emf;
+ }
+
+ /**
+ * A part of the facade over the JPA API
+ * Create an EntityManager from the EntityManagerFactory wrapped by this persistence context
+ * @param tenantId
+ * @return
+ */
+ protected EntityManager createEntityManager(String tenantId) {
+ return getEmf().createEntityManager();
+ }
+
+ /**
+ * Build the set of properties used to create the JAXBContext based on the EntityManagerFactory that
+ * this PersistenceContext wraps
+ * @param session
+ * @return
+ * @throws IOException
+ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ protected Map<String, Object> createJAXBProperties(AbstractSession session) throws IOException {
+ Map<String, Object> properties = new HashMap<String, Object>(1);
+ List<Object> metadataLocations = new ArrayList<Object>();
+
+ addDynamicXMLMetadataSources(metadataLocations, session);
+ String oxmLocation = (String) emf.getProperties().get("eclipselink.jpa-rs.oxm");
+
+ if (oxmLocation != null) {
+ metadataLocations.add(oxmLocation);
+ }
+
+ Object passedOXMLocations = emf.getProperties().get(JAXBContextProperties.OXM_METADATA_SOURCE);
+ if (passedOXMLocations != null) {
+ if (passedOXMLocations instanceof Collection) {
+ metadataLocations.addAll((Collection) passedOXMLocations);
+ } else {
+ metadataLocations.add(passedOXMLocations);
+ }
+ }
+
+ metadataLocations.add(new LinkMetadataSource());
+ metadataLocations.add(new ReportQueryResultListMetadataSource());
+ metadataLocations.add(new ReportQueryResultListItemMetadataSource());
+ metadataLocations.add(new SingleResultQueryListMetadataSource());
+ metadataLocations.add(new SimpleHomogeneousListMetadataSource());
+ metadataLocations.add(new ReportQueryResultCollectionMetadataSource());
+ metadataLocations.add(new ReadAllQueryResultCollectionMetadataSource());
+
+ metadataLocations.add(new JavaLangMetadataSource());
+ metadataLocations.add(new JavaMathMetadataSource());
+ metadataLocations.add(new JavaUtilMetadataSource());
+ metadataLocations.add(new LinkV2MetadataSource());
+ metadataLocations.add(new ItemLinksMetadataSource());
+ metadataLocations.add(new ErrorResponseMetadataSource());
+
+ properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, metadataLocations);
properties.put(JAXBContextProperties.SESSION_EVENT_LISTENER, new PreLoginMappingAdapter(session));
-
- // Bug 410095 - JSON_WRAPPER_AS_ARRAY_NAME property doesn't work when jaxb context is created using DynamicJAXBContextFactory
- //properties.put(JAXBContextProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
-
- return properties;
- }
-
- /**
- * A part of the facade over the JPA API
- * Delete the given entity in JPA and commit the changes
- */
- public void delete(Map<String, String> tenantId, String type, Object id) {
- EntityManager em = getEmf().createEntityManager(tenantId);
-
- try {
- transaction.beginTransaction(em);
- Object entity = em.find(getClass(type), id);
- if (entity != null) {
- em.remove(entity);
- }
- transaction.commitTransaction(em);
- } catch (RollbackException ex) {
- throw JPARSException.exceptionOccurred(ex);
- } catch (Exception ex) {
- transaction.rollbackTransaction(em);
- throw JPARSException.exceptionOccurred(ex);
- } finally {
- em.close();
- }
- }
-
- /**
- * Does exist.
- *
- * @param tenantId the tenant id
- * @param entity the entity
- * @return true, if successful
- */
- public boolean doesExist(Map<String, String> tenantId, Object entity) {
- DatabaseSession session = JpaHelper.getDatabaseSession(getEmf());
- return session.doesObjectExist(entity);
- }
-
- /**
- * Finalize.
- */
- @Override
- public void finalize() {
- this.emf.close();
- this.emf = null;
- this.jaxbContext = null;
- }
-
- /**
- * A part of the facade over the JPA API
- * Find an entity with the given name and id in JPA
- * @param entityName
- * @param id
- * @return
- */
- public Object find(String entityName, Object id) {
- return find(null, entityName, id);
- }
-
- /**
- * A part of the facade over the JPA API
- * Find an entity with the given name and id in JPA
- * @param tenantId
- * @param entityName
- * @param id
- * @return
- */
- public Object find(Map<String, String> tenantId, String entityName, Object id) {
- return find(tenantId, entityName, id, null);
- }
-
- /**
- * A part of the facade over the JPA API
- * Find an entity with the given name and id in JPA
- * @param tenantId
- * @param entityName
- * @param id
- * @param properties - query hints used on the find
- * @return
- */
- public Object find(Map<String, String> tenantId, String entityName, Object id, Map<String, Object> properties) {
- EntityManager em = getEmf().createEntityManager(tenantId);
-
- try {
- return em.find(getClass(entityName), id, properties);
- } finally {
- em.close();
- }
- }
-
- /**
- * Update or add attribute.
- *
- * @param tenantId the tenant id
- * @param entityName the entity name
- * @param id the id
- * @param properties the properties
- * @param attribute the attribute
- * @param attributeValue the attribute value
- * @param partner the partner
- * @return the object
- */
- public Object updateOrAddAttribute(Map<String, String> tenantId, String entityName, Object id, Map<String, Object> properties, String attribute, Object attributeValue, String partner) {
- EntityManager em = getEmf().createEntityManager(tenantId);
-
- try {
- ClassDescriptor descriptor = getServerSession().getClassDescriptor(getClass(entityName));
- DatabaseMapping mapping = descriptor.getMappingForAttributeName(attribute);
+
+ // Bug 410095 - JSON_WRAPPER_AS_ARRAY_NAME property doesn't work when jaxb context is created using DynamicJAXBContextFactory
+ //properties.put(JAXBContextProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
+
+ return properties;
+ }
+
+ /**
+ * A part of the facade over the JPA API
+ * Delete the given entity in JPA and commit the changes
+ */
+ public void delete(Map<String, String> tenantId, String type, Object id) {
+ EntityManager em = getEmf().createEntityManager(tenantId);
+
+ try {
+ transaction.beginTransaction(em);
+ Object entity = em.find(getClass(type), id);
+ if (entity != null) {
+ em.remove(entity);
+ }
+ transaction.commitTransaction(em);
+ } catch (RollbackException ex) {
+ throw JPARSException.exceptionOccurred(ex);
+ } catch (Exception ex) {
+ transaction.rollbackTransaction(em);
+ throw JPARSException.exceptionOccurred(ex);
+ } finally {
+ em.close();
+ }
+ }
+
+ /**
+ * Does exist.
+ *
+ * @param tenantId the tenant id
+ * @param entity the entity
+ * @return true, if successful
+ */
+ public boolean doesExist(Map<String, String> tenantId, Object entity) {
+ DatabaseSession session = JpaHelper.getDatabaseSession(getEmf());
+ return session.doesObjectExist(entity);
+ }
+
+ /**
+ * Finalize.
+ */
+ @Override
+ public void finalize() {
+ this.emf.close();
+ this.emf = null;
+ this.jaxbContext = null;
+ }
+
+ /**
+ * A part of the facade over the JPA API
+ * Find an entity with the given name and id in JPA
+ * @param entityName
+ * @param id
+ * @return
+ */
+ public Object find(String entityName, Object id) {
+ return find(null, entityName, id);
+ }
+
+ /**
+ * A part of the facade over the JPA API
+ * Find an entity with the given name and id in JPA
+ * @param tenantId
+ * @param entityName
+ * @param id
+ * @return
+ */
+ public Object find(Map<String, String> tenantId, String entityName, Object id) {
+ return find(tenantId, entityName, id, null);
+ }
+
+ /**
+ * A part of the facade over the JPA API
+ * Find an entity with the given name and id in JPA
+ * @param tenantId
+ * @param entityName
+ * @param id
+ * @param properties - query hints used on the find
+ * @return
+ */
+ public Object find(Map<String, String> tenantId, String entityName, Object id, Map<String, Object> properties) {
+ EntityManager em = getEmf().createEntityManager(tenantId);
+
+ try {
+ return em.find(getClass(entityName), id, properties);
+ } finally {
+ em.close();
+ }
+ }
+
+ /**
+ * Update or add attribute.
+ *
+ * @param tenantId the tenant id
+ * @param entityName the entity name
+ * @param id the id
+ * @param properties the properties
+ * @param attribute the attribute
+ * @param attributeValue the attribute value
+ * @param partner the partner
+ * @return the object
+ */
+ public Object updateOrAddAttribute(Map<String, String> tenantId, String entityName, Object id, Map<String, Object> properties, String attribute, Object attributeValue, String partner) {
+ EntityManager em = getEmf().createEntityManager(tenantId);
+
+ try {
+ ClassDescriptor descriptor = getServerSession().getClassDescriptor(getClass(entityName));
+ DatabaseMapping mapping = descriptor.getMappingForAttributeName(attribute);
Object object;
- if (mapping == null) {
- return null;
- } else if (mapping.isObjectReferenceMapping() || mapping.isCollectionMapping()) {
- DatabaseMapping partnerMapping = null;
- if (partner != null) {
+ if (mapping == null) {
+ return null;
+ } else if (mapping.isObjectReferenceMapping() || mapping.isCollectionMapping()) {
+ DatabaseMapping partnerMapping = null;
+ if (partner != null) {
ClassDescriptor referenceDescriptor = mapping.getReferenceDescriptor();
- partnerMapping = referenceDescriptor.getMappingForAttributeName(partner);
- if (partnerMapping == null) {
- return null;
- }
- }
- transaction.beginTransaction(em);
- try {
- object = em.find(getClass(entityName), id, properties);
- if (object == null) {
- return null;
- }
- attributeValue = em.merge(attributeValue);
- setMappingValueInObject(object, attributeValue, mapping, partnerMapping);
- transaction.commitTransaction(em);
- } catch (RollbackException e) {
- JPARSLogger.exception("exception_while_updating_attribute", new Object[] { entityName, getName() }, e);
- return null;
- } catch (Exception e) {
- JPARSLogger.exception("exception_while_updating_attribute", new Object[] { entityName, getName() }, e);
- transaction.rollbackTransaction(em);
- return null;
- }
- } else {
- return null;
- }
- return object;
- } finally {
- em.close();
- }
- }
-
- /**
- * Removes the attribute.
- *
- * @param tenantId the tenant id
- * @param entityName the entity name
- * @param id the id
- * @param attribute the attribute
+ partnerMapping = referenceDescriptor.getMappingForAttributeName(partner);
+ if (partnerMapping == null) {
+ return null;
+ }
+ }
+ transaction.beginTransaction(em);
+ try {
+ object = em.find(getClass(entityName), id, properties);
+ if (object == null) {
+ return null;
+ }
+ attributeValue = em.merge(attributeValue);
+ setMappingValueInObject(object, attributeValue, mapping, partnerMapping);
+ transaction.commitTransaction(em);
+ } catch (RollbackException e) {
+ JPARSLogger.exception("exception_while_updating_attribute", new Object[] { entityName, getName() }, e);
+ return null;
+ } catch (Exception e) {
+ JPARSLogger.exception("exception_while_updating_attribute", new Object[] { entityName, getName() }, e);
+ transaction.rollbackTransaction(em);
+ return null;
+ }
+ } else {
+ return null;
+ }
+ return object;
+ } finally {
+ em.close();
+ }
+ }
+
+ /**
+ * Removes the attribute.
+ *
+ * @param tenantId the tenant id
+ * @param entityName the entity name
+ * @param id the id
+ * @param attribute the attribute
* @param listItemId
* @param entity
- * @param partner the partner
- * @return the object
- *
- */
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public Object removeAttribute(Map<String, String> tenantId, String entityName, Object id, String attribute, String listItemId, Object entity, String partner)
- {
- EntityManager em = getEmf().createEntityManager(tenantId);
- String fieldName = null;
-
- try {
- Class<?> clazz = getClass(entityName);
- ClassDescriptor descriptor = getServerSession().getClassDescriptor(clazz);
- DatabaseMapping mapping = descriptor.getMappingForAttributeName(attribute);
- if (mapping == null) {
- return null;
- } else if (mapping.isObjectReferenceMapping() || mapping.isCollectionMapping()) {
- DatabaseMapping partnerMapping = null;
- Object originalAttributeValue = null;
+ * @param partner the partner
+ * @return the object
+ *
+ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public Object removeAttribute(Map<String, String> tenantId, String entityName, Object id, String attribute, String listItemId, Object entity, String partner)
+ {
+ EntityManager em = getEmf().createEntityManager(tenantId);
+ String fieldName = null;
+
+ try {
+ Class<?> clazz = getClass(entityName);
+ ClassDescriptor descriptor = getServerSession().getClassDescriptor(clazz);
+ DatabaseMapping mapping = descriptor.getMappingForAttributeName(attribute);
+ if (mapping == null) {
+ return null;
+ } else if (mapping.isObjectReferenceMapping() || mapping.isCollectionMapping()) {
+ DatabaseMapping partnerMapping = null;
+ Object originalAttributeValue = null;
ClassDescriptor referenceDescriptor = mapping.getReferenceDescriptor();
- if (partner != null) {
- partnerMapping = referenceDescriptor.getMappingForAttributeName(partner);
- if (partnerMapping == null) {
- return null;
- }
- }
+ if (partner != null) {
+ partnerMapping = referenceDescriptor.getMappingForAttributeName(partner);
+ if (partnerMapping == null) {
+ return null;
+ }
+ }
Field[] fields;
- if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
- fields = AccessController.doPrivileged(new PrivilegedGetDeclaredFields(clazz));
- } else {
- fields = PrivilegedAccessHelper.getDeclaredFields(clazz);
- }
-
+ if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
+ fields = AccessController.doPrivileged(new PrivilegedGetDeclaredFields(clazz));
+ } else {
+ fields = PrivilegedAccessHelper.getDeclaredFields(clazz);
+ }
+
for (Field field : fields) {
- fieldName = field.getName();
- if (fieldName.equals(attribute)) {
- try {
- // call clear on this collection
- Object attributeValue = getAttribute(entity, attribute);
- originalAttributeValue = attributeValue;
- if (attributeValue instanceof Collection) {
- if (listItemId == null) {
- // no collection member specified in request (listItemId=null) remove entire collection
- ((Collection) attributeValue).clear();
- } else {
- Object realListItemId = IdHelper.buildId(this, referenceDescriptor.getAlias(), listItemId);
- Object member = this.find(referenceDescriptor.getAlias(), realListItemId);
- ((Collection) attributeValue).remove(member);
- }
- }
- break;
- } catch (Exception e) {
- e.printStackTrace();
- return null;
- }
- }
- }
-
- transaction.beginTransaction(em);
- entity = em.merge(entity);
- removeMappingValueFromObject(entity, originalAttributeValue, mapping, partnerMapping);
- transaction.commitTransaction(em);
- return entity;
- }
- return null;
- } catch (Exception e) {
- JPARSLogger.exception("exception_while_removing_attribute", new Object[] { fieldName, entityName, getName() }, e);
- transaction.rollbackTransaction(em);
- return null;
- } finally {
- em.close();
- }
- }
-
- @SuppressWarnings("unchecked")
- private Object getAttribute(Object entity, String propertyName) {
- try {
- BeanInfo info = Introspector.getBeanInfo(entity.getClass(), Object.class);
- PropertyDescriptor[] props = info.getPropertyDescriptors();
- for (PropertyDescriptor pd : props) {
- String name = pd.getName();
- if (propertyName.equals(name)) {
- Method getter = pd.getReadMethod();
+ fieldName = field.getName();
+ if (fieldName.equals(attribute)) {
+ try {
+ // call clear on this collection
+ Object attributeValue = getAttribute(entity, attribute);
+ originalAttributeValue = attributeValue;
+ if (attributeValue instanceof Collection) {
+ if (listItemId == null) {
+ // no collection member specified in request (listItemId=null) remove entire collection
+ ((Collection) attributeValue).clear();
+ } else {
+ Object realListItemId = IdHelper.buildId(this, referenceDescriptor.getAlias(), listItemId);
+ Object member = this.find(referenceDescriptor.getAlias(), realListItemId);
+ ((Collection) attributeValue).remove(member);
+ }
+ }
+ break;
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+ }
+
+ transaction.beginTransaction(em);
+ entity = em.merge(entity);
+ removeMappingValueFromObject(entity, originalAttributeValue, mapping, partnerMapping);
+ transaction.commitTransaction(em);
+ return entity;
+ }
+ return null;
+ } catch (Exception e) {
+ JPARSLogger.exception("exception_while_removing_attribute", new Object[] { fieldName, entityName, getName() }, e);
+ transaction.rollbackTransaction(em);
+ return null;
+ } finally {
+ em.close();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private Object getAttribute(Object entity, String propertyName) {
+ try {
+ BeanInfo info = Introspector.getBeanInfo(entity.getClass(), Object.class);
+ PropertyDescriptor[] props = info.getPropertyDescriptors();
+ for (PropertyDescriptor pd : props) {
+ String name = pd.getName();
+ if (propertyName.equals(name)) {
+ Method getter = pd.getReadMethod();
Object value;
- if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
- value = AccessController.doPrivileged(new PrivilegedMethodInvoker(getter, entity));
- } else {
- value = PrivilegedAccessHelper.invokeMethod(getter, entity);
- }
- return value;
- }
- }
- } catch (Exception ex) {
- return null;
- }
- return null;
- }
-
- @SuppressWarnings("rawtypes")
- protected void removeMappingValueFromObject(Object object, Object attributeValue, DatabaseMapping mapping, DatabaseMapping partner) {
- if (mapping.isObjectReferenceMapping()) {
- Object currentValue = mapping.getRealAttributeValueFromObject(object, (AbstractSession) getServerSession());
- if (currentValue.equals(attributeValue)) {
- ((ObjectReferenceMapping) mapping).getIndirectionPolicy().setRealAttributeValueInObject(object, null, true);
- if (partner != null) {
- removeMappingValueFromObject(attributeValue, object, partner, null);
- }
- }
- } else if (mapping.isCollectionMapping()) {
- boolean removed = ((Collection) mapping.getRealAttributeValueFromObject(object, (AbstractSession) getServerSession())).remove(attributeValue);
- if (removed && partner != null) {
- removeMappingValueFromObject(attributeValue, object, partner, null);
- }
- }
- }
-
- /**
- * Gets the base uri.
- *
- * @return the base uri
- */
- public URI getBaseURI() {
- return baseURI;
- }
-
- /**
- * Look-up the given entity name in the EntityManagerFactory and return the class
- * is describes
- * @param entityName
- * @return
- */
- public Class<?> getClass(String entityName) {
- ClassDescriptor descriptor = getDescriptor(entityName);
- if (descriptor == null) {
- return null;
- }
- return descriptor.getJavaClass();
- }
-
- /**
- * Gets the jpa server session.
- *
- * @return the jpa server session
- */
- public DatabaseSession getServerSession() {
- // Fix for bug 390786 - JPA-RS: ClassCastException retrieving metadata for Composite Persistence Unit
+ if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
+ value = AccessController.doPrivileged(new PrivilegedMethodInvoker(getter, entity));
+ } else {
+ value = PrivilegedAccessHelper.invokeMethod(getter, entity);
+ }
+ return value;
+ }
+ }
+ } catch (Exception ex) {
+ return null;
+ }
+ return null;
+ }
+
+ @SuppressWarnings("rawtypes")
+ protected void removeMappingValueFromObject(Object object, Object attributeValue, DatabaseMapping mapping, DatabaseMapping partner) {
+ if (mapping.isObjectReferenceMapping()) {
+ Object currentValue = mapping.getRealAttributeValueFromObject(object, (AbstractSession) getServerSession());
+ if (currentValue.equals(attributeValue)) {
+ ((ObjectReferenceMapping) mapping).getIndirectionPolicy().setRealAttributeValueInObject(object, null, true);
+ if (partner != null) {
+ removeMappingValueFromObject(attributeValue, object, partner, null);
+ }
+ }
+ } else if (mapping.isCollectionMapping()) {
+ boolean removed = ((Collection) mapping.getRealAttributeValueFromObject(object, (AbstractSession) getServerSession())).remove(attributeValue);
+ if (removed && partner != null) {
+ removeMappingValueFromObject(attributeValue, object, partner, null);
+ }
+ }
+ }
+
+ /**
+ * Gets the base uri.
+ *
+ * @return the base uri
+ */
+ public URI getBaseURI() {
+ return baseURI;
+ }
+
+ /**
+ * Look-up the given entity name in the EntityManagerFactory and return the class
+ * is describes
+ * @param entityName
+ * @return
+ */
+ public Class<?> getClass(String entityName) {
+ ClassDescriptor descriptor = getDescriptor(entityName);
+ if (descriptor == null) {
+ return null;
+ }
+ return descriptor.getJavaClass();
+ }
+
+ /**
+ * Gets the jpa server session.
+ *
+ * @return the jpa server session
+ */
+ public DatabaseSession getServerSession() {
+ // Fix for bug 390786 - JPA-RS: ClassCastException retrieving metadata for Composite Persistence Unit
return JpaHelper.getDatabaseSession(emf);
- }
-
- /**
- * Gets the client session.
- *
- * @param em the em
- * @return the client session
- */
- public AbstractSession getClientSession(EntityManager em) {
+ }
+
+ /**
+ * Gets the client session.
+ *
+ * @param em the em
+ * @return the client session
+ */
+ public AbstractSession getClientSession(EntityManager em) {
UnitOfWork uow = JpaHelper.getEntityManager(em).getUnitOfWork();
- return (AbstractSession) uow;
- }
-
- /**
- * Lookup the descriptor for the given entity name.
- * This method will look first in the EntityManagerFactory wrapped by this persistence context
- * and return that descriptor. If one does not exist, it search the JAXBContext and return
- * a descriptor from there.
- * @param entityName
- * @return
- */
- public ClassDescriptor getDescriptor(String entityName) {
- DatabaseSession session = getServerSession();
- ClassDescriptor descriptor = session.getDescriptorForAlias(entityName);
- if (descriptor == null) {
+ return (AbstractSession) uow;
+ }
+
+ /**
+ * Lookup the descriptor for the given entity name.
+ * This method will look first in the EntityManagerFactory wrapped by this persistence context
+ * and return that descriptor. If one does not exist, it search the JAXBContext and return
+ * a descriptor from there.
+ * @param entityName
+ * @return
+ */
+ public ClassDescriptor getDescriptor(String entityName) {
+ DatabaseSession session = getServerSession();
+ ClassDescriptor descriptor = session.getDescriptorForAlias(entityName);
+ if (descriptor == null) {
for (Object ajaxBSession : getJAXBContext().getXMLContext().getSessions()) {
- descriptor = ((Session) ajaxBSession).getClassDescriptorForAlias(entityName);
- if (descriptor != null) {
- break;
- }
- }
- }
- return descriptor;
- }
-
- /**
- * Gets the descriptor for class.
- *
- * @param clazz the clazz
- * @return the descriptor for class
- */
- @SuppressWarnings("rawtypes")
- public ClassDescriptor getDescriptorForClass(Class clazz) {
- DatabaseSession session = getServerSession();
- ClassDescriptor descriptor = session.getDescriptor(clazz);
- if (descriptor == null) {
- return getJAXBDescriptorForClass(clazz);
- }
- return descriptor;
- }
-
- /**
- * Gets the jAXB descriptor for class.
- *
- * @param clazz the clazz
- * @return the jAXB descriptor for class
- */
- @SuppressWarnings("rawtypes")
- public ClassDescriptor getJAXBDescriptorForClass(Class clazz) {
- ClassDescriptor descriptor = null;
+ descriptor = ((Session) ajaxBSession).getClassDescriptorForAlias(entityName);
+ if (descriptor != null) {
+ break;
+ }
+ }
+ }
+ return descriptor;
+ }
+
+ /**
+ * Gets the descriptor for class.
+ *
+ * @param clazz the clazz
+ * @return the descriptor for class
+ */
+ @SuppressWarnings("rawtypes")
+ public ClassDescriptor getDescriptorForClass(Class clazz) {
+ DatabaseSession session = getServerSession();
+ ClassDescriptor descriptor = session.getDescriptor(clazz);
+ if (descriptor == null) {
+ return getJAXBDescriptorForClass(clazz);
+ }
+ return descriptor;
+ }
+
+ /**
+ * Gets the jAXB descriptor for class.
+ *
+ * @param clazz the clazz
+ * @return the jAXB descriptor for class
+ */
+ @SuppressWarnings("rawtypes")
+ public ClassDescriptor getJAXBDescriptorForClass(Class clazz) {
+ ClassDescriptor descriptor = null;
for (Object ajaxBSession : getJAXBContext().getXMLContext().getSessions()) {
- descriptor = ((Session) ajaxBSession).getClassDescriptor(clazz);
- if (descriptor != null) {
- break;
- }
- }
- return descriptor;
- }
-
- /**
- * Gets the emf.
- *
- * @return the emf
- */
- public EntityManagerFactory getEmf() {
- return emf;
- }
-
- /**
- * Gets the jAXB context.
- *
- * @return the jAXB context
- */
- public JAXBContext getJAXBContext() {
- return jaxbContext;
- }
-
- /**
- * Gets the name.
- *
- * @return the name
- */
- public String getName() {
- return name;
- }
-
- /**
- * A part of the facade over the JPA API
- * Call jpa merge on the given object and commit
- * If the passed object is a list, we will iterate through the
- * list and merge each member
- * @param tenantId
- * @param entity
- * @return
- */
-
- @SuppressWarnings("rawtypes")
- public Object merge(Map<String, String> tenantId, Object entity) {
- EntityManager em = getEmf().createEntityManager(tenantId);
+ descriptor = ((Session) ajaxBSession).getClassDescriptor(clazz);
+ if (descriptor != null) {
+ break;
+ }
+ }
+ return descriptor;
+ }
+
+ /**
+ * Gets the emf.
+ *
+ * @return the emf
+ */
+ public EntityManagerFactory getEmf() {
+ return emf;
+ }
+
+ /**
+ * Gets the jAXB context.
+ *
+ * @return the jAXB context
+ */
+ public JAXBContext getJAXBContext() {
+ return jaxbContext;
+ }
+
+ /**
+ * Gets the name.
+ *
+ * @return the name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * A part of the facade over the JPA API
+ * Call jpa merge on the given object and commit
+ * If the passed object is a list, we will iterate through the
+ * list and merge each member
+ * @param tenantId
+ * @param entity
+ * @return
+ */
+
+ @SuppressWarnings("rawtypes")
+ public Object merge(Map<String, String> tenantId, Object entity) {
+ EntityManager em = getEmf().createEntityManager(tenantId);
Object mergedEntity;
- try {
- transaction.beginTransaction(em);
- if (entity instanceof List) {
- List<Object> mergeList = new ArrayList<Object>();
- for (Object o : (List) entity) {
- mergeList.add(em.merge(o));
- }
- mergedEntity = mergeList;
- } else {
- mergedEntity = em.merge(entity);
- }
- transaction.commitTransaction(em);
- return mergedEntity;
- } catch (RollbackException ex) {
- throw JPARSException.exceptionOccurred(ex);
- } catch (Exception ex) {
- transaction.rollbackTransaction(em);
- throw JPARSException.exceptionOccurred(ex);
- } finally {
- em.close();
- }
- }
-
- /**
- * A convenience method to create a new dynamic entity of the given type
- * @param type
- * @return
- */
- public DynamicEntity newEntity(String type) {
- return newEntity(null, type);
- }
-
- /**
- * A convenience method to create a new dynamic entity of the given type
- * @param tenantId
- * @param type
- * @return
- */
- public DynamicEntity newEntity(Map<String, String> tenantId, String type) {
- JPADynamicHelper helper = new JPADynamicHelper(getEmf());
+ try {
+ transaction.beginTransaction(em);
+ if (entity instanceof List) {
+ List<Object> mergeList = new ArrayList<Object>();
+ for (Object o : (List) entity) {
+ mergeList.add(em.merge(o));
+ }
+ mergedEntity = mergeList;
+ } else {
+ mergedEntity = em.merge(entity);
+ }
+ transaction.commitTransaction(em);
+ return mergedEntity;
+ } catch (RollbackException ex) {
+ throw JPARSException.exceptionOccurred(ex);
+ } catch (Exception ex) {
+ transaction.rollbackTransaction(em);
+ throw JPARSException.exceptionOccurred(ex);
+ } finally {
+ em.close();
+ }
+ }
+
+ /**
+ * A convenience method to create a new dynamic entity of the given type
+ * @param type
+ * @return
+ */
+ public DynamicEntity newEntity(String type) {
+ return newEntity(null, type);
+ }
+
+ /**
+ * A convenience method to create a new dynamic entity of the given type
+ * @param tenantId
+ * @param type
+ * @return
+ */
+ public DynamicEntity newEntity(Map<String, String> tenantId, String type) {
+ JPADynamicHelper helper = new JPADynamicHelper(getEmf());
DynamicEntity entity;
- try {
- entity = helper.newDynamicEntity(type);
- } catch (IllegalArgumentException e) {
- ClassDescriptor descriptor = getDescriptor(type);
- if (descriptor != null) {
- DynamicType jaxbType = (DynamicType) descriptor.getProperty(DynamicType.DESCRIPTOR_PROPERTY);
- if (jaxbType != null) {
- return jaxbType.newDynamicEntity();
- }
- }
- JPARSLogger.exception("exception_thrown_while_creating_dynamic_entity", new Object[] { type }, e);
- throw e;
- }
- return entity;
- }
-
- /**
- * Query execute update.
- *
- * @param tenantId the tenant id
- * @param name the name
- * @param parameters the parameters
- * @param hints the hints
- * @return the int
- */
- public int queryExecuteUpdate(Map<String, String> tenantId, String name, Map<?, ?> parameters, Map<String, ?> hints) {
- EntityManager em = getEmf().createEntityManager(tenantId);
- try {
- Query query = constructQuery(em, name, parameters, hints);
- transaction.beginTransaction(em);
- int result = query.executeUpdate();
- transaction.commitTransaction(em);
- return result;
- } catch (RollbackException ex) {
- throw JPARSException.exceptionOccurred(ex);
- } catch (Exception ex) {
- transaction.rollbackTransaction(em);
- throw JPARSException.exceptionOccurred(ex);
- } finally {
- em.close();
- }
- }
-
- /**
- * Query multiple results.
- *
- * @param tenantId the tenant id
- * @param name the name
- * @param parameters the parameters
- * @param hints the hints
- * @return the list
- */
- @SuppressWarnings("rawtypes")
- public List queryMultipleResults(Map<String, String> tenantId, String name, Map<?, ?> parameters, Map<String, ?> hints) {
- EntityManager em = getEmf().createEntityManager(tenantId);
- try {
- Query query = constructQuery(em, name, parameters, hints);
- return query.getResultList();
- } finally {
- em.close();
- }
- }
-
- @SuppressWarnings("rawtypes")
- protected Query constructQuery(EntityManager em, String name, Map<?, ?> parameters, Map<String, ?> hints) {
- Query query = em.createNamedQuery(name);
- DatabaseQuery dbQuery = ((EJBQueryImpl<?>) query).getDatabaseQuery();
- if (parameters != null) {
- Iterator i = parameters.keySet().iterator();
- while (i.hasNext()) {
- String key = (String) i.next();
- Class parameterClass = null;
- int index = dbQuery.getArguments().indexOf(key);
- if (index >= 0) {
- parameterClass = dbQuery.getArgumentTypes().get(index);
- }
- Object parameter = parameters.get(key);
- if (parameterClass != null) {
- parameter = ConversionManager.getDefaultManager().convertObject(parameter, parameterClass);
- }
- query.setParameter(key, parameter);
- }
- }
- if (hints != null) {
- for (String key : hints.keySet()) {
- query.setHint(key, hints.get(key));
- }
- }
- return query;
- }
-
- /**
- * Builds the query.
- *
- * @param tenantId the tenant id
- * @param name the name
- * @param parameters the parameters
- * @param hints the hints
- * @return the query
- */
- @SuppressWarnings("rawtypes")
- public Query buildQuery(Map<String, String> tenantId, String name, Map<?, ?> parameters, Map<String, ?> hints) {
- EntityManager em = getEmf().createEntityManager(tenantId);
- Query query = em.createNamedQuery(name);
- DatabaseQuery dbQuery = ((EJBQueryImpl<?>) query).getDatabaseQuery();
- if (parameters != null) {
- Iterator i = parameters.keySet().iterator();
- while (i.hasNext()) {
- String key = (String) i.next();
- Class parameterClass = null;
- int index = dbQuery.getArguments().indexOf(key);
- if (index >= 0) {
- parameterClass = dbQuery.getArgumentTypes().get(index);
- }
- Object parameter = parameters.get(key);
- if (parameterClass != null) {
- parameter = ConversionManager.getDefaultManager().convertObject(parameter, parameterClass);
- }
- query.setParameter(key, parameter);
- }
- }
- if (hints != null) {
- for (String key : hints.keySet()) {
- query.setHint(key, hints.get(key));
- }
- }
- return query;
- }
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- protected void setMappingValueInObject(Object object, Object attributeValue, DatabaseMapping mapping, DatabaseMapping partner) {
- if (mapping.isObjectReferenceMapping()) {
- ((ObjectReferenceMapping) mapping).getIndirectionPolicy().setRealAttributeValueInObject(object, attributeValue, true);
- if (partner != null) {
- setMappingValueInObject(attributeValue, object, partner, null);
- }
- } else if (mapping.isCollectionMapping()) {
- ((Collection) mapping.getAttributeValueFromObject(object)).add(attributeValue);
- if (partner != null) {
- setMappingValueInObject(attributeValue, object, partner, null);
- }
- }
- }
-
- /**
- * Stop the current application instance
- */
- public void stop() {
- if (emf != null && emf.isOpen()) {
- emf.close();
- }
- this.emf = null;
- this.jaxbContext = null;
- }
-
- /**
- * To string.
- *
- * @return the string
- */
- public String toString() {
- return "PersistenceContext(name:" + getName() + ", version:" + getVersion() + ", identityHashCode:" + System.identityHashCode(this) + ")";
- }
-
- /**
- * Unmarshal entity.
- *
- * @param type the type of the entity to unmarshal
- * @param acceptedMediaType the accepted media type
- * @param in the input stream to unmarshal
- * @return the object
- * @throws JAXBException the JAXB exception
- */
- public Object unmarshalEntity(String type, MediaType acceptedMediaType, InputStream in) throws JAXBException {
- if (JPARSLogger.isLoggableFinest()) {
- in = in.markSupported() ? in : new BufferedInputStream(in);
- // TODO: Make readlimit configurable. Some http servers allow http post size to be unlimited.
- // If this is the case and if an application is sending huge post requests while jpars log
- // level configured to finest, this readlimit might not be sufficient.
- in.mark(52428800); // (~50MB)
- JPARSLogger.entering(CLASS_NAME, "unmarshalEntity", in);
- }
- Object unmarshalled = unmarshal(getClass(type), acceptedMediaType, in);
- JPARSLogger.exiting(CLASS_NAME, "unmarshalEntity", new Object[] { unmarshalled.getClass().getName(), unmarshalled });
- return unmarshalled;
- }
-
- /**
- * Unmarshal.
- *
- * @param type the type of the entity to unmarshal
- * @param acceptedMediaType the accepted media type
- * @param in the input stream to unmarshal
- * @return the object
- * @throws JAXBException the JAXB exception
- */
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public Object unmarshal(Class type, MediaType acceptedMediaType, InputStream in) throws JAXBException {
- Unmarshaller unmarshaller = getJAXBContext().createUnmarshaller();
- unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, Boolean.FALSE);
- unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, acceptedMediaType.toString());
- unmarshaller.setAdapter(new LinkAdapter(getBaseURI().toString(), this));
- unmarshaller.setEventHandler(new ValidationEventHandler() {
- @Override
- /*
- * ReferenceAdaptor unmarshal throws exception if the object referred by a link
- * doesn't exist, and this handler is required to interrupt the unmarshal
- * operation under this condition.
- * (non-Javadoc) @see javax.xml.bind.ValidationEventHandler#handleEvent(javax.xml.bind.ValidationEvent)
- *
- */
- public boolean handleEvent(ValidationEvent event) {
- if (event.getSeverity() != ValidationEvent.WARNING) {
- // ValidationEventLocator eventLocator = event.getLocator();
- // Throwable throwable = event.getLinkedException();
+ try {
+ entity = helper.newDynamicEntity(type);
+ } catch (IllegalArgumentException e) {
+ ClassDescriptor descriptor = getDescriptor(type);
+ if (descriptor != null) {
+ DynamicType jaxbType = (DynamicType) descriptor.getProperty(DynamicType.DESCRIPTOR_PROPERTY);
+ if (jaxbType != null) {
+ return jaxbType.newDynamicEntity();
+ }
+ }
+ JPARSLogger.exception("exception_thrown_while_creating_dynamic_entity", new Object[] { type }, e);
+ throw e;
+ }
+ return entity;
+ }
+
+ /**
+ * Query execute update.
+ *
+ * @param tenantId the tenant id
+ * @param name the name
+ * @param parameters the parameters
+ * @param hints the hints
+ * @return the int
+ */
+ public int queryExecuteUpdate(Map<String, String> tenantId, String name, Map<?, ?> parameters, Map<String, ?> hints) {
+ EntityManager em = getEmf().createEntityManager(tenantId);
+ try {
+ Query query = constructQuery(em, name, parameters, hints);
+ transaction.beginTransaction(em);
+ int result = query.executeUpdate();
+ transaction.commitTransaction(em);
+ return result;
+ } catch (RollbackException ex) {
+ throw JPARSException.exceptionOccurred(ex);
+ } catch (Exception ex) {
+ transaction.rollbackTransaction(em);
+ throw JPARSException.exceptionOccurred(ex);
+ } finally {
+ em.close();
+ }
+ }
+
+ /**
+ * Query multiple results.
+ *
+ * @param tenantId the tenant id
+ * @param name the name
+ * @param parameters the parameters
+ * @param hints the hints
+ * @return the list
+ */
+ @SuppressWarnings("rawtypes")
+ public List queryMultipleResults(Map<String, String> tenantId, String name, Map<?, ?> parameters, Map<String, ?> hints) {
+ EntityManager em = getEmf().createEntityManager(tenantId);
+ try {
+ Query query = constructQuery(em, name, parameters, hints);
+ return query.getResultList();
+ } finally {
+ em.close();
+ }
+ }
+
+ @SuppressWarnings("rawtypes")
+ protected Query constructQuery(EntityManager em, String name, Map<?, ?> parameters, Map<String, ?> hints) {
+ Query query = em.createNamedQuery(name);
+ DatabaseQuery dbQuery = ((EJBQueryImpl<?>) query).getDatabaseQuery();
+ if (parameters != null) {
+ Iterator i = parameters.keySet().iterator();
+ while (i.hasNext()) {
+ String key = (String) i.next();
+ Class parameterClass = null;
+ int index = dbQuery.getArguments().indexOf(key);
+ if (index >= 0) {
+ parameterClass = dbQuery.getArgumentTypes().get(index);
+ }
+ Object parameter = parameters.get(key);
+ if (parameterClass != null) {
+ parameter = ConversionManager.getDefaultManager().convertObject(parameter, parameterClass);
+ }
+ query.setParameter(key, parameter);
+ }
+ }
+ if (hints != null) {
+ for (String key : hints.keySet()) {
+ query.setHint(key, hints.get(key));
+ }
+ }
+ return query;
+ }
+
+ /**
+ * Builds the query.
+ *
+ * @param tenantId the tenant id
+ * @param name the name
+ * @param parameters the parameters
+ * @param hints the hints
+ * @return the query
+ */
+ @SuppressWarnings("rawtypes")
+ public Query buildQuery(Map<String, String> tenantId, String name, Map<?, ?> parameters, Map<String, ?> hints) {
+ EntityManager em = getEmf().createEntityManager(tenantId);
+ Query query = em.createNamedQuery(name);
+ DatabaseQuery dbQuery = ((EJBQueryImpl<?>) query).getDatabaseQuery();
+ if (parameters != null) {
+ Iterator i = parameters.keySet().iterator();
+ while (i.hasNext()) {
+ String key = (String) i.next();
+ Class parameterClass = null;
+ int index = dbQuery.getArguments().indexOf(key);
+ if (index >= 0) {
+ parameterClass = dbQuery.getArgumentTypes().get(index);
+ }
+ Object parameter = parameters.get(key);
+ if (parameterClass != null) {
+ parameter = ConversionManager.getDefaultManager().convertObject(parameter, parameterClass);
+ }
+ query.setParameter(key, parameter);
+ }
+ }
+ if (hints != null) {
+ for (String key : hints.keySet()) {
+ query.setHint(key, hints.get(key));
+ }
+ }
+ return query;
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ protected void setMappingValueInObject(Object object, Object attributeValue, DatabaseMapping mapping, DatabaseMapping partner) {
+ if (mapping.isObjectReferenceMapping()) {
+ ((ObjectReferenceMapping) mapping).getIndirectionPolicy().setRealAttributeValueInObject(object, attributeValue, true);
+ if (partner != null) {
+ setMappingValueInObject(attributeValue, object, partner, null);
+ }
+ } else if (mapping.isCollectionMapping()) {
+ ((Collection) mapping.getAttributeValueFromObject(object)).add(attributeValue);
+ if (partner != null) {
+ setMappingValueInObject(attributeValue, object, partner, null);
+ }
+ }
+ }
+
+ /**
+ * Stop the current application instance
+ */
+ public void stop() {
+ if (emf != null && emf.isOpen()) {
+ emf.close();
+ }
+ this.emf = null;
+ this.jaxbContext = null;
+ }
+
+ /**
+ * To string.
+ *
+ * @return the string
+ */
+ public String toString() {
+ return "PersistenceContext(name:" + getName() + ", version:" + getVersion() + ", identityHashCode:" + System.identityHashCode(this) + ")";
+ }
+
+ /**
+ * Unmarshal entity.
+ *
+ * @param type the type of the entity to unmarshal
+ * @param acceptedMediaType the accepted media type
+ * @param in the input stream to unmarshal
+ * @return the object
+ * @throws JAXBException the JAXB exception
+ */
+ public Object unmarshalEntity(String type, MediaType acceptedMediaType, InputStream in) throws JAXBException {
+ if (JPARSLogger.isLoggableFinest()) {
+ in = in.markSupported() ? in : new BufferedInputStream(in);
+ // TODO: Make readlimit configurable. Some http servers allow http post size to be unlimited.
+ // If this is the case and if an application is sending huge post requests while jpars log
+ // level configured to finest, this readlimit might not be sufficient.
+ in.mark(52428800); // (~50MB)
+ JPARSLogger.entering(CLASS_NAME, "unmarshalEntity", in);
+ }
+ Object unmarshalled = unmarshal(getClass(type), acceptedMediaType, in);
+ JPARSLogger.exiting(CLASS_NAME, "unmarshalEntity", new Object[] { unmarshalled.getClass().getName(), unmarshalled });
+ return unmarshalled;
+ }
+
+ /**
+ * Unmarshal.
+ *
+ * @param type the type of the entity to unmarshal
+ * @param acceptedMediaType the accepted media type
+ * @param in the input stream to unmarshal
+ * @return the object
+ * @throws JAXBException the JAXB exception
+ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public Object unmarshal(Class type, MediaType acceptedMediaType, InputStream in) throws JAXBException {
+ Unmarshaller unmarshaller = getJAXBContext().createUnmarshaller();
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, Boolean.FALSE);
+ unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, acceptedMediaType.toString());
+ unmarshaller.setAdapter(new LinkAdapter(getBaseURI().toString(), this));
+ unmarshaller.setEventHandler(new ValidationEventHandler() {
+ @Override
+ /*
+ * ReferenceAdaptor unmarshal throws exception if the object referred by a link
+ * doesn't exist, and this handler is required to interrupt the unmarshal
+ * operation under this condition.
+ * (non-Javadoc) @see javax.xml.bind.ValidationEventHandler#handleEvent(javax.xml.bind.ValidationEvent)
+ *
+ */
+ public boolean handleEvent(ValidationEvent event) {
+ if (event.getSeverity() != ValidationEvent.WARNING) {
+ // ValidationEventLocator eventLocator = event.getLocator();
+ // Throwable throwable = event.getLinkedException();
// nothing is really useful to check for us in eventLocator
- // and linked exception, just return false;
- return false;
- }
- return true;
- }
- });
-
- for (XmlAdapter adapter : getAdapters()) {
- unmarshaller.setAdapter(adapter);
- }
-
- if (acceptedMediaType == MediaType.APPLICATION_JSON_TYPE) {
- // Part of the fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=394059
- // This issue happens when request has objects derived from an abstract class.
- // JSON_INCLUDE_ROOT is set to false for JPA-RS. This means JSON requests won't have root tag.
- // The unmarshal method needs to be called with type, so that moxy can unmarshal the message based on type.
- // For xml, root tag is always set, unmarshaller must use root of the message for unmarshalling and type should
- // not be passed to unmarshal for xml type requests.
- JAXBElement<?> element = unmarshaller.unmarshal(new StreamSource(in), type);
- if (element.getValue() instanceof List<?>) {
- for (Object object : (List<?>) element.getValue()) {
- wrap(object);
- }
- return element.getValue();
- } else {
- wrap(element.getValue());
- }
- return element.getValue();
- }
-
- Object domainObject = unmarshaller.unmarshal(new StreamSource(in));
- if (domainObject instanceof List<?>) {
- for (Object object : (List<?>) domainObject) {
- wrap(object);
- }
- return domainObject;
- } else {
- wrap(domainObject);
- }
- return domainObject;
- }
-
- /**
- * Make adjustments to an unmarshalled entity based on what is found in the weaved fields
- *
- * @param entity
- * @return
- */
- protected Object wrap(Object entity) {
- if ((entity != null) && (PersistenceWeavedRest.class.isAssignableFrom(entity.getClass()))) {
- if (!doesExist(null, entity)) {
- return entity;
- }
- ClassDescriptor descriptor = getJAXBDescriptorForClass(entity.getClass());
- if (entity instanceof FetchGroupTracker) {
- FetchGroup fetchGroup = new FetchGroup();
- for (DatabaseMapping mapping : descriptor.getMappings()) {
- if (!(mapping instanceof XMLInverseReferenceMapping)) {
- fetchGroup.addAttribute(mapping.getAttributeName());
- }
- }
- (new FetchGroupManager()).setObjectFetchGroup(entity, fetchGroup, null);
- ((FetchGroupTracker) entity)._persistence_setSession(JpaHelper.getDatabaseSession(getEmf()));
- } else if (descriptor.hasRelationships()) {
- for (DatabaseMapping mapping : descriptor.getMappings()) {
- if (mapping instanceof XMLInverseReferenceMapping) {
- // we require Fetch groups to handle relationships
- JPARSLogger.error("weaving_required_for_relationships", new Object[] {});
- throw JPARSException.invalidConfiguration();
- }
- }
- }
- }
- return entity;
- }
-
- /**
- * Marshall an entity to either JSON or XML
- * Calling this method, will treat relationships as unfetched in the XML/JSON and marshall them as links
- * rather than attempting to marshall the data in those relationships
- * @param object
- * @param mediaType
- * @param output
- * @throws JAXBException
- */
- public void marshallEntity(Object object, MediaType mediaType, OutputStream output) throws JAXBException {
- JPARSLogger.entering(CLASS_NAME, "marshallEntity", new Object[] { object, mediaType });
- marshall(object, mediaType, output, true);
- JPARSLogger.exiting(CLASS_NAME, "marshallEntity", this, object, mediaType);
- }
-
- /**
- * Marshall an entity to either JSON or XML
- * @param object
- * @param mediaType
- * @param output
- * @param sendRelationships if this is set to true, relationships will be sent as links instead of sending
- * the actual objects in the relationships
- * @throws JAXBException
- */
- @SuppressWarnings({ "rawtypes", "unchecked" })
- public void marshall(Object object, MediaType mediaType, OutputStream output, boolean sendRelationships) throws JAXBException {
- if (sendRelationships) {
- preMarshallEntity(object);
- }
-
- Marshaller marshaller = getJAXBContext().createMarshaller();
- marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, mediaType.toString());
- marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
- marshaller.setProperty(MarshallerProperties.JSON_REDUCE_ANY_ARRAYS, true);
-
- marshaller.setProperty(MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
-
- marshaller.setAdapter(new LinkAdapter(getBaseURI().toString(), this));
- marshaller.setAdapter(new RelationshipLinkAdapter(getBaseURI().toString(), this));
-
- for (XmlAdapter adapter : getAdapters()) {
- marshaller.setAdapter(adapter);
- }
-
- if (mediaType == MediaType.APPLICATION_XML_TYPE && object instanceof List) {
- marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
- XMLOutputFactory outputFactory = XMLOutputFactory.newFactory();
+ // and linked exception, just return false;
+ return false;
+ }
+ return true;
+ }
+ });
+
+ for (XmlAdapter adapter : getAdapters()) {
+ unmarshaller.setAdapter(adapter);
+ }
+
+ if (acceptedMediaType == MediaType.APPLICATION_JSON_TYPE) {
+ // Part of the fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=394059
+ // This issue happens when request has objects derived from an abstract class.
+ // JSON_INCLUDE_ROOT is set to false for JPA-RS. This means JSON requests won't have root tag.
+ // The unmarshal method needs to be called with type, so that moxy can unmarshal the message based on type.
+ // For xml, root tag is always set, unmarshaller must use root of the message for unmarshalling and type should
+ // not be passed to unmarshal for xml type requests.
+ JAXBElement<?> element = unmarshaller.unmarshal(new StreamSource(in), type);
+ if (element.getValue() instanceof List<?>) {
+ for (Object object : (List<?>) element.getValue()) {
+ wrap(object);
+ }
+ return element.getValue();
+ } else {
+ wrap(element.getValue());
+ }
+ return element.getValue();
+ }
+
+ Object domainObject = unmarshaller.unmarshal(new StreamSource(in));
+ if (domainObject instanceof List<?>) {
+ for (Object object : (List<?>) domainObject) {
+ wrap(object);
+ }
+ return domainObject;
+ } else {
+ wrap(domainObject);
+ }
+ return domainObject;
+ }
+
+ /**
+ * Make adjustments to an unmarshalled entity based on what is found in the weaved fields
+ *
+ * @param entity
+ * @return
+ */
+ protected Object wrap(Object entity) {
+ if ((entity != null) && (PersistenceWeavedRest.class.isAssignableFrom(entity.getClass()))) {
+ if (!doesExist(null, entity)) {
+ return entity;
+ }
+ ClassDescriptor descriptor = getJAXBDescriptorForClass(entity.getClass());
+ if (entity instanceof FetchGroupTracker) {
+ FetchGroup fetchGroup = new FetchGroup();
+ for (DatabaseMapping mapping : descriptor.getMappings()) {
+ if (!(mapping instanceof XMLInverseReferenceMapping)) {
+ fetchGroup.addAttribute(mapping.getAttributeName());
+ }
+ }
+ (new FetchGroupManager()).setObjectFetchGroup(entity, fetchGroup, null);
+ ((FetchGroupTracker) entity)._persistence_setSession(JpaHelper.getDatabaseSession(getEmf()));
+ } else if (descriptor.hasRelationships()) {
+ for (DatabaseMapping mapping : descriptor.getMappings()) {
+ if (mapping instanceof XMLInverseReferenceMapping) {
+ // we require Fetch groups to handle relationships
+ JPARSLogger.error("weaving_required_for_relationships", new Object[] {});
+ throw JPARSException.invalidConfiguration();
+ }
+ }
+ }
+ }
+ return entity;
+ }
+
+ /**
+ * Marshall an entity to either JSON or XML
+ * Calling this method, will treat relationships as unfetched in the XML/JSON and marshall them as links
+ * rather than attempting to marshall the data in those relationships
+ * @param object
+ * @param mediaType
+ * @param output
+ * @throws JAXBException
+ */
+ public void marshallEntity(Object object, MediaType mediaType, OutputStream output) throws JAXBException {
+ JPARSLogger.entering(CLASS_NAME, "marshallEntity", new Object[] { object, mediaType });
+ marshall(object, mediaType, output, true);
+ JPARSLogger.exiting(CLASS_NAME, "marshallEntity", this, object, mediaType);
+ }
+
+ public void marshallEntity(Object object, List<String> fields, MediaType mediaType, OutputStream output) throws JAXBException {
+ JPARSLogger.entering(CLASS_NAME, "marshallEntity", new Object[] { object, fields, mediaType });
+ marshall(object, mediaType, output, true, fields);
+ JPARSLogger.exiting(CLASS_NAME, "marshallEntity", this, object, mediaType);
+ }
+
+ /**
+ * Marshall an entity to either JSON or XML.
+ *
+ * @param object
+ * @param mediaType
+ * @param output
+ * @param sendRelationships if this is set to true, relationships will be sent as links instead of sending.
+ * the actual objects in the relationships
+ * @throws JAXBException
+ */
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ public void marshall(Object object, MediaType mediaType, OutputStream output, boolean sendRelationships) throws JAXBException {
+ marshall(object, mediaType, output, sendRelationships, null);
+ }
+
+ /**
+ * Marshall an entity to either JSON or XML.
+ *
+ * @param object
+ * @param mediaType
+ * @param output
+ * @param sendRelationships if this is set to true, relationships will be sent as links instead of sending
+ * the actual objects in the relationships.
+ * @param fields A list of fields to marshall.
+ * @throws JAXBException
+ */
+ public void marshall(final Object object, final MediaType mediaType, final OutputStream output, boolean sendRelationships, final List<String> fields) throws JAXBException {
+ if (sendRelationships) {
+ preMarshallEntity(object);
+ }
+
+ Marshaller marshaller = getJAXBContext().createMarshaller();
+ marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, mediaType.toString());
+ marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
+ marshaller.setProperty(MarshallerProperties.JSON_REDUCE_ANY_ARRAYS, true);
+
+ marshaller.setProperty(MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
+
+ marshaller.setAdapter(new LinkAdapter(getBaseURI().toString(), this));
+ marshaller.setAdapter(new RelationshipLinkAdapter(getBaseURI().toString(), this));
+
+ for (XmlAdapter adapter : getAdapters()) {
+ marshaller.setAdapter(adapter);
+ }
+
+ if (fields != null) {
+ marshaller.setProperty(MarshallerProperties.OBJECT_GRAPH, createObjectGraph(object, fields));
+ }
+
+ if (mediaType == MediaType.APPLICATION_XML_TYPE && object instanceof List) {
+ marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
+ XMLOutputFactory outputFactory = XMLOutputFactory.newFactory();
XMLStreamWriter writer;
- try {
- writer = outputFactory.createXMLStreamWriter(output);
- writer.writeStartDocument();
- writer.writeStartElement(ReservedWords.JPARS_LIST_GROUPING_NAME);
- for (Object o : (List<Object>) object) {
- marshaller.marshal(o, writer);
- }
- writer.writeEndDocument();
- writer.flush();
- postMarshallEntity(object);
- } catch (Exception ex) {
- throw JPARSException.exceptionOccurred(ex);
- }
- } else {
- marshaller.marshal(object, output);
- postMarshallEntity(object);
- }
- }
-
- /**
- * Process an entity and add any additional data that needs to be added prior to marshalling
- * This method will both single entities and lists of entities
- * @param object
- */
- @SuppressWarnings("rawtypes")
- protected void preMarshallEntity(Object object) {
- if (object instanceof List) {
+ try {
+ writer = outputFactory.createXMLStreamWriter(output);
+ writer.writeStartDocument();
+ writer.writeStartElement(ReservedWords.JPARS_LIST_GROUPING_NAME);
+ for (Object o : (List<Object>) object) {
+ marshaller.marshal(o, writer);
+ }
+ writer.writeEndDocument();
+ writer.flush();
+ postMarshallEntity(object);
+ } catch (Exception ex) {
+ throw JPARSException.exceptionOccurred(ex);
+ }
+ } else {
+ marshaller.marshal(object, output);
+ postMarshallEntity(object);
+ }
+ }
+
+ /**
+ * Process an entity and add any additional data that needs to be added prior to marshalling
+ * This method will both single entities and lists of entities
+ * @param object
+ */
+ @SuppressWarnings("rawtypes")
+ protected void preMarshallEntity(Object object) {
+ if (object instanceof List) {
for (Object o : ((List) object)) {
preMarshallIndividualEntity(o);
- }
- } else {
- preMarshallIndividualEntity(object);
- }
- }
-
- /**
- * Add any data required prior to marshalling an entity to XML or JSON
- * In general, this will only affect fields that have been weaved into the object
- * @param entity
- */
- @SuppressWarnings("rawtypes")
- protected void preMarshallIndividualEntity(Object entity) {
- if (entity instanceof ReportQueryResultListItem) {
- ReportQueryResultListItem item = (ReportQueryResultListItem) entity;
+ }
+ } else {
+ preMarshallIndividualEntity(object);
+ }
+ }
+
+ /**
+ * Add any data required prior to marshalling an entity to XML or JSON
+ * In general, this will only affect fields that have been weaved into the object
+ * @param entity
+ */
+ @SuppressWarnings("rawtypes")
+ protected void preMarshallIndividualEntity(Object entity) {
+ if (entity instanceof ReportQueryResultListItem) {
+ ReportQueryResultListItem item = (ReportQueryResultListItem) entity;
for (JAXBElement field : item.getFields()) {
- // one or more fields in the MultiResultQueryListItem might be a domain object,
- // so, we need to set the relationshipInfo for those domain objects.
+ // one or more fields in the MultiResultQueryListItem might be a domain object,
+ // so, we need to set the relationshipInfo for those domain objects.
setRelationshipInfo(field.getValue());
- }
- } else if (entity instanceof SingleResultQueryList) {
- SingleResultQueryList item = (SingleResultQueryList) entity;
+ }
+ } else if (entity instanceof SingleResultQueryList) {
+ SingleResultQueryList item = (SingleResultQueryList) entity;
for (JAXBElement field : item.getFields()) {
- // one or more fields in the SingleResultQueryList might be a domain object,
- // so, we need to set the relationshipInfo for those domain objects.
+ // one or more fields in the SingleResultQueryList might be a domain object,
+ // so, we need to set the relationshipInfo for those domain objects.
setRelationshipInfo(field.getValue());
- }
- } else if (entity instanceof ReportQueryResultList) {
- ReportQueryResultList list = (ReportQueryResultList) entity;
+ }
+ } else if (entity instanceof ReportQueryResultList) {
+ ReportQueryResultList list = (ReportQueryResultList) entity;
for (ReportQueryResultListItem item : list.getItems()) {
for (JAXBElement field : item.getFields()) {
- // one or more fields in the MultiResultQueryList might be a domain object,
- // so, we need to set the relationshipInfo for those domain objects.
+ // one or more fields in the MultiResultQueryList might be a domain object,
+ // so, we need to set the relationshipInfo for those domain objects.
setRelationshipInfo(field.getValue());
- }
- }
- } else if (entity instanceof ReadAllQueryResultCollection) {
- ReadAllQueryResultCollection list = (ReadAllQueryResultCollection) entity;
- List<Object> items = list.getItems();
- if ((items != null) && (!items.isEmpty())) {
+ }
+ }
+ } else if (entity instanceof ReadAllQueryResultCollection) {
+ ReadAllQueryResultCollection list = (ReadAllQueryResultCollection) entity;
+ List<Object> items = list.getItems();
+ if ((items != null) && (!items.isEmpty())) {
for (Object item : items) {
- setRelationshipInfo(item);
- }
- }
- } else if (entity instanceof ReportQueryResultCollection) {
- ReportQueryResultCollection list = (ReportQueryResultCollection) entity;
- List<ReportQueryResultListItem> items = list.getItems();
- if ((items != null) && (!items.isEmpty())) {
+ setRelationshipInfo(item);
+ }
+ }
+ } else if (entity instanceof ReportQueryResultCollection) {
+ ReportQueryResultCollection list = (ReportQueryResultCollection) entity;
+ List<ReportQueryResultListItem> items = list.getItems();
+ if ((items != null) && (!items.isEmpty())) {
for (ReportQueryResultListItem item : items) {
- setRelationshipInfo(item);
- }
- }
- } else {
- setRelationshipInfo(entity);
- }
- }
-
- private void setRelationshipInfo(Object entity) {
- if ((entity != null) && (entity instanceof PersistenceWeavedRest)) {
- ClassDescriptor descriptor = getServerSession().getClassDescriptor(entity.getClass());
- if (descriptor != null) {
- ((PersistenceWeavedRest) entity)._persistence_setRelationships(new ArrayList<RelationshipInfo>());
- for (DatabaseMapping mapping : descriptor.getMappings()) {
- if (mapping.isForeignReferenceMapping()) {
- ForeignReferenceMapping frMapping = (ForeignReferenceMapping) mapping;
- RelationshipInfo info = new RelationshipInfo();
- info.setAttributeName(frMapping.getAttributeName());
- info.setOwningEntity(entity);
- info.setOwningEntityAlias(descriptor.getAlias());
- info.setPersistencePrimaryKey(descriptor.getObjectBuilder().extractPrimaryKeyFromObject(entity, (AbstractSession) getServerSession()));
- ((PersistenceWeavedRest) entity)._persistence_getRelationships().add(info);
- } else if (mapping.isEISMapping()) {
- if (mapping instanceof EISCompositeCollectionMapping) {
- EISCompositeCollectionMapping eisMapping = (EISCompositeCollectionMapping) mapping;
- RelationshipInfo info = new RelationshipInfo();
- info.setAttributeName(eisMapping.getAttributeName());
- info.setOwningEntity(entity);
- info.setOwningEntityAlias(descriptor.getAlias());
- info.setPersistencePrimaryKey(descriptor.getObjectBuilder().extractPrimaryKeyFromObject(entity, (AbstractSession) getServerSession()));
- ((PersistenceWeavedRest) entity)._persistence_getRelationships().add(info);
- }
- }
- }
- }
- }
- }
-
- @SuppressWarnings("rawtypes")
- protected void postMarshallEntity(Object object) {
- if (object instanceof List) {
+ setRelationshipInfo(item);
+ }
+ }
+ } else {
+ setRelationshipInfo(entity);
+ }
+ }
+
+ private void setRelationshipInfo(Object entity) {
+ if ((entity != null) && (entity instanceof PersistenceWeavedRest)) {
+ ClassDescriptor descriptor = getServerSession().getClassDescriptor(entity.getClass());
+ if (descriptor != null) {
+ ((PersistenceWeavedRest) entity)._persistence_setRelationships(new ArrayList<RelationshipInfo>());
+ for (DatabaseMapping mapping : descriptor.getMappings()) {
+ if (mapping.isForeignReferenceMapping()) {
+ ForeignReferenceMapping frMapping = (ForeignReferenceMapping) mapping;
+ RelationshipInfo info = new RelationshipInfo();
+ info.setAttributeName(frMapping.getAttributeName());
+ info.setOwningEntity(entity);
+ info.setOwningEntityAlias(descriptor.getAlias());
+ info.setPersistencePrimaryKey(descriptor.getObjectBuilder().extractPrimaryKeyFromObject(entity, (AbstractSession) getServerSession()));
+ ((PersistenceWeavedRest) entity)._persistence_getRelationships().add(info);
+ } else if (mapping.isEISMapping()) {
+ if (mapping instanceof EISCompositeCollectionMapping) {
+ EISCompositeCollectionMapping eisMapping = (EISCompositeCollectionMapping) mapping;
+ RelationshipInfo info = new RelationshipInfo();
+ info.setAttributeName(eisMapping.getAttributeName());
+ info.setOwningEntity(entity);
+ info.setOwningEntityAlias(descriptor.getAlias());
+ info.setPersistencePrimaryKey(descriptor.getObjectBuilder().extractPrimaryKeyFromObject(entity, (AbstractSession) getServerSession()));
+ ((PersistenceWeavedRest) entity)._persistence_getRelationships().add(info);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings("rawtypes")
+ protected void postMarshallEntity(Object object) {
+ if (object instanceof List) {
for (Object entity : ((List) object)) {
- if (entity instanceof PersistenceWeavedRest) {
- ((PersistenceWeavedRest) entity)._persistence_setRelationships(new ArrayList<RelationshipInfo>());
- }
- }
- } else if (object instanceof PersistenceWeavedRest) {
- ((PersistenceWeavedRest) object)._persistence_setRelationships(new ArrayList<RelationshipInfo>());
- }
- }
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- protected List<XmlAdapter> getAdapters() throws JPARSException {
- if (adapters != null) {
- return adapters;
- }
- adapters = new ArrayList<XmlAdapter>();
- try {
- for (ClassDescriptor desc : this.getServerSession().getDescriptors().values()) {
- // avoid embeddables
- if (!desc.isAggregateCollectionDescriptor() && !desc.isAggregateDescriptor()) {
- Class clz = desc.getJavaClass();
- String referenceAdapterName = RestAdapterClassWriter.constructClassNameForReferenceAdapter(clz.getName());
- ClassLoader cl = getServerSession().getDatasourcePlatform().getConversionManager().getLoader();
- Class referenceAdaptorClass = Class.forName(referenceAdapterName, true, cl);
- Class[] argTypes = { String.class, PersistenceContext.class };
- Constructor referenceAdaptorConstructor = referenceAdaptorClass.getDeclaredConstructor(argTypes);
- Object[] args = new Object[] { getBaseURI().toString(), this };
- adapters.add((XmlAdapter) referenceAdaptorConstructor.newInstance(args));
- }
- }
- } catch (Exception ex) {
- ex.printStackTrace();
- throw JPARSException.exceptionOccurred(ex);
- }
- return adapters;
- }
-
- private boolean getWeavingProperty() {
- // Initialize the properties with their defaults first
- boolean restWeavingEnabled = true;
- boolean fetchGroupWeavingEnabled = true;
- boolean weavingEnabled = true;
-
- Map<String, Object> properties = this.emf.getProperties();
-
- for (Map.Entry<String, Object> entry : properties.entrySet()) {
- String key = entry.getKey();
- Object value = entry.getValue();
-
- if (key.equals(PersistenceUnitProperties.WEAVING)) {
- if (!("true".equalsIgnoreCase((String) value)) && !("static".equalsIgnoreCase((String) value))) {
- weavingEnabled = false;
- }
- }
-
- if (key.equals(PersistenceUnitProperties.WEAVING_REST)) {
- if (!("true".equalsIgnoreCase((String) value))) {
- restWeavingEnabled = false;
- }
- }
-
- if (key.equals(PersistenceUnitProperties.WEAVING_FETCHGROUPS)) {
- if (!("true".equalsIgnoreCase((String) value))) {
- fetchGroupWeavingEnabled = false;
- }
- }
- }
- return (weavingEnabled && restWeavingEnabled && fetchGroupWeavingEnabled);
- }
-
- /**
+ if (entity instanceof PersistenceWeavedRest) {
+ ((PersistenceWeavedRest) entity)._persistence_setRelationships(new ArrayList<RelationshipInfo>());
+ }
+ }
+ } else if (object instanceof PersistenceWeavedRest) {
+ ((PersistenceWeavedRest) object)._persistence_setRelationships(new ArrayList<RelationshipInfo>());
+ }
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ protected List<XmlAdapter> getAdapters() throws JPARSException {
+ if (adapters != null) {
+ return adapters;
+ }
+ adapters = new ArrayList<XmlAdapter>();
+ try {
+ for (ClassDescriptor desc : this.getServerSession().getDescriptors().values()) {
+ // avoid embeddables
+ if (!desc.isAggregateCollectionDescriptor() && !desc.isAggregateDescriptor()) {
+ Class clz = desc.getJavaClass();
+ String referenceAdapterName = RestAdapterClassWriter.constructClassNameForReferenceAdapter(clz.getName());
+ ClassLoader cl = getServerSession().getDatasourcePlatform().getConversionManager().getLoader();
+ Class referenceAdaptorClass = Class.forName(referenceAdapterName, true, cl);
+ Class[] argTypes = { String.class, PersistenceContext.class };
+ Constructor referenceAdaptorConstructor = referenceAdaptorClass.getDeclaredConstructor(argTypes);
+ Object[] args = new Object[] { getBaseURI().toString(), this };
+ adapters.add((XmlAdapter) referenceAdaptorConstructor.newInstance(args));
+ }
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ throw JPARSException.exceptionOccurred(ex);
+ }
+ return adapters;
+ }
+
+ private boolean getWeavingProperty() {
+ // Initialize the properties with their defaults first
+ boolean restWeavingEnabled = true;
+ boolean fetchGroupWeavingEnabled = true;
+ boolean weavingEnabled = true;
+
+ Map<String, Object> properties = this.emf.getProperties();
+
+ for (Map.Entry<String, Object> entry : properties.entrySet()) {
+ String key = entry.getKey();
+ Object value = entry.getValue();
+
+ if (key.equals(PersistenceUnitProperties.WEAVING)) {
+ if (!("true".equalsIgnoreCase((String) value)) && !("static".equalsIgnoreCase((String) value))) {
+ weavingEnabled = false;
+ }
+ }
+
+ if (key.equals(PersistenceUnitProperties.WEAVING_REST)) {
+ if (!("true".equalsIgnoreCase((String) value))) {
+ restWeavingEnabled = false;
+ }
+ }
+
+ if (key.equals(PersistenceUnitProperties.WEAVING_FETCHGROUPS)) {
+ if (!("true".equalsIgnoreCase((String) value))) {
+ fetchGroupWeavingEnabled = false;
+ }
+ }
+ }
+ return (weavingEnabled && restWeavingEnabled && fetchGroupWeavingEnabled);
+ }
+
+ /**
* Gets the supported feature set.
- *
+ *
* @return the supported feature set.
- */
+ */
public FeatureSet getSupportedFeatureSet() {
return version.getFeatureSet();
- }
-
- /**
+ }
+
+ /**
* Finds out is given query pageable or not.
- *
+ *
* @param queryName named query to check.
* @return true if pageable, false if not.
- */
+ */
public boolean isQueryPageable(String queryName) {
return getPageableQueries().get(queryName) != null;
}
@@ -1383,13 +1410,13 @@ public class PersistenceContext {
*/
public RestPageableQuery getPageableQuery(String queryName) {
return getPageableQueries().get(queryName);
- }
-
- /**
+ }
+
+ /**
* Sets the version.
- *
+ *
* @param version the new version.
- */
+ */
public void setVersion(String version) {
this.version = ServiceVersion.fromCode(version);
}
@@ -1434,55 +1461,71 @@ public class PersistenceContext {
}
}
}
- }
-
- /* (non-Javadoc)
- * @see java.lang.Object#hashCode()
- */
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((name == null) ? 0 : name.hashCode());
- result = prime * result + ((version == null) ? 0 : version.hashCode());
- return result;
- }
-
- /* (non-Javadoc)
- * @see java.lang.Object#equals(java.lang.Object)
- */
- @Override
- public boolean equals(Object other) {
- if (this == other) {
- return true;
- }
-
- if (other == null) {
- return false;
- }
-
- if (getClass() != other.getClass()) {
- return false;
- }
-
- PersistenceContext otherContext = (PersistenceContext) other;
-
- if (name == null) {
- if (otherContext.name != null) {
- return false;
- }
- } else if (!name.equals(otherContext.name)) {
- return false;
- }
-
- if (version == null) {
- if (otherContext.version != null) {
- return false;
- }
- } else if (!version.equals(otherContext.version)) {
- return false;
- }
-
- return true;
- }
-}
+ }
+
+ /**
+ * Creates {@link ObjectGraph} from the given list of entity attributes.
+ *
+ * @param entity An entity to create object graph for.
+ * @param fields A list of entity attributes.
+ * @return Object graph
+ */
+ private ObjectGraph createObjectGraph(final Object entity, final List<String> fields) {
+ ObjectGraph objectGraph = getJAXBContext().createObjectGraph(entity.getClass());
+ objectGraph.addAttributeNodes("_persistence_links", "_persistence_relationshipInfo");
+ for (String field : fields) {
+ objectGraph.addAttributeNodes(field);
+ }
+ return objectGraph;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ result = prime * result + ((version == null) ? 0 : version.hashCode());
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (other == null) {
+ return false;
+ }
+
+ if (getClass() != other.getClass()) {
+ return false;
+ }
+
+ PersistenceContext otherContext = (PersistenceContext) other;
+
+ if (name == null) {
+ if (otherContext.name != null) {
+ return false;
+ }
+ } else if (!name.equals(otherContext.name)) {
+ return false;
+ }
+
+ if (version == null) {
+ if (otherContext.version != null) {
+ return false;
+ }
+ } else if (!version.equals(otherContext.version)) {
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/jpa/rs/features/FeatureSet.java b/dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/jpa/rs/features/FeatureSet.java
index 7bb153b..46d4134 100644
--- a/dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/jpa/rs/features/FeatureSet.java
+++ b/dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/jpa/rs/features/FeatureSet.java
@@ -18,8 +18,14 @@ package org.eclipse.persistence.jpa.rs.features;
*/
public interface FeatureSet {
public enum Feature {
- NO_PAGING, /* not pageable resurces */
- PAGING /* pageable resources */
+ /* Not pageable resources */
+ NO_PAGING,
+
+ /* Pageable resources */
+ PAGING,
+
+ /* Fields filtering (fields, exclFields query parameters) */
+ FIELDS_FILTERING
}
/**
diff --git a/dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/jpa/rs/features/FeatureSetV2.java b/dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/jpa/rs/features/FeatureSetV2.java
index 7fadd96..85fc9c0 100644
--- a/dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/jpa/rs/features/FeatureSetV2.java
+++ b/dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/jpa/rs/features/FeatureSetV2.java
@@ -28,6 +28,7 @@ public class FeatureSetV2 implements FeatureSet {
switch (feature) {
case NO_PAGING:
case PAGING:
+ case FIELDS_FILTERING:
return true;
default:
return false;
@@ -42,7 +43,6 @@ public class FeatureSetV2 implements FeatureSet {
switch (feature) {
case PAGING:
return new PagingResponseBuilder();
- case NO_PAGING:
default:
return new SelfLinksResponseBuilder();
}
diff --git a/dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/jpa/rs/features/fieldsfiltering/FieldsFilteringValidator.java b/dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/jpa/rs/features/fieldsfiltering/FieldsFilteringValidator.java
new file mode 100644
index 0000000..641adcd
--- /dev/null
+++ b/dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/jpa/rs/features/fieldsfiltering/FieldsFilteringValidator.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Dmitry Kornilov - initial implementation
+ ******************************************************************************/
+
+package org.eclipse.persistence.jpa.rs.features.fieldsfiltering;
+
+import org.eclipse.persistence.jpa.rs.PersistenceContext;
+import org.eclipse.persistence.jpa.rs.exceptions.JPARSException;
+import org.eclipse.persistence.jpa.rs.resources.common.AbstractResource;
+import org.eclipse.persistence.mappings.DatabaseMapping;
+
+import javax.ws.rs.core.UriInfo;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Fields filtering feature validator/processor.
+ *
+ * @author Dmitry Kornilov
+ */
+public final class FieldsFilteringValidator {
+ public static final String FIELDS_PARAM_NAME = "fields";
+ public static final String EXCL_FIELDS_PARAM_NAME = "exclFields";
+
+ private final UriInfo uri;
+ private final Object entity;
+ private final PersistenceContext context;
+ private final Map<String, Object> queryParameters;
+ private List<String> fields;
+
+ /**
+ * Creates the validator.
+ *
+ * @param uri request URI.
+ */
+ public FieldsFilteringValidator(PersistenceContext context, UriInfo uri, Object entity) {
+ queryParameters = AbstractResource.getQueryParameters(uri);
+ this.uri = uri;
+ this.entity = entity;
+ this.context = context;
+ }
+
+ /**
+ * Checks if request is valid.
+ *
+ * @return true if request is valid and feature is supported, false if request is valid but feature is not supported.
+ * @throws org.eclipse.persistence.jpa.rs.exceptions.JPARSException in case of any validation errors.
+ */
+ public boolean isFeatureApplicable() throws JPARSException {
+ if (!queryParameters.containsKey(FIELDS_PARAM_NAME) && !queryParameters.containsKey(EXCL_FIELDS_PARAM_NAME)) {
+ return false;
+ }
+
+ // Throw exception if both 'fields' and 'exclFields' present
+ if (queryParameters.containsKey(FIELDS_PARAM_NAME) && queryParameters.containsKey(EXCL_FIELDS_PARAM_NAME)) {
+ // TODO throw the right exception
+ throw new IllegalArgumentException("");
+ }
+
+ if (queryParameters.containsKey(FIELDS_PARAM_NAME)) {
+ // fields
+ fields = Arrays.asList(((String) queryParameters.get(FIELDS_PARAM_NAME)).split("\\s*,\\s*"));
+ } else {
+ // exclFields
+ List<String> exclFields = Arrays.asList(((String) queryParameters.get(EXCL_FIELDS_PARAM_NAME)).split("\\s*,\\s*"));
+
+ // Get attribute mappings from class descriptor. We just need an attributes list actually
+ List<DatabaseMapping> mappings = context.getServerSession().getProject().getDescriptors().get(entity.getClass()).getMappings();
+
+ // Build fields list as all fields without the excluded ones
+ fields = new ArrayList<String>();
+ for (DatabaseMapping mapping : mappings) {
+ if (!exclFields.contains(mapping.getAttributeName())) {
+ fields.add(mapping.getAttributeName());
+ }
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Gets a list of fields need to be returned in response. Has to be called after isFeatureApplicable() method.
+ *
+ * @return A list of entity attributes which have to be included in response.
+ */
+ public List<String> getFields() {
+ return fields;
+ }
+}
diff --git a/dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/jpa/rs/resources/common/AbstractEntityResource.java b/dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/jpa/rs/resources/common/AbstractEntityResource.java
index 055a8ae..42f1603 100644
--- a/dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/jpa/rs/resources/common/AbstractEntityResource.java
+++ b/dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/jpa/rs/resources/common/AbstractEntityResource.java
@@ -8,7 +8,7 @@
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
- * Dmitry Kornilov - pagination related changes
+ * Dmitry Kornilov - pagination and fields filtering related changes
******************************************************************************/
package org.eclipse.persistence.jpa.rs.resources.common;
@@ -24,6 +24,7 @@ import org.eclipse.persistence.jpa.rs.exceptions.JPARSException;
import org.eclipse.persistence.jpa.rs.features.FeatureResponseBuilder;
import org.eclipse.persistence.jpa.rs.features.FeatureSet;
import org.eclipse.persistence.jpa.rs.features.FeatureSet.Feature;
+import org.eclipse.persistence.jpa.rs.features.fieldsfiltering.FieldsFilteringValidator;
import org.eclipse.persistence.jpa.rs.features.paging.PageableFieldValidator;
import org.eclipse.persistence.jpa.rs.util.IdHelper;
import org.eclipse.persistence.jpa.rs.util.JPARSLogger;
@@ -129,14 +130,27 @@ public abstract class AbstractEntityResource extends AbstractResource {
JPARSLogger.entering(CLASS_NAME, "findInternal", new Object[] { "GET", version, persistenceUnit, type, id, uriInfo.getRequestUri().toASCIIString() });
try {
- PersistenceContext context = getPersistenceContext(persistenceUnit, type, uriInfo.getBaseUri(), version, null);
- Map<String, String> discriminators = getMatrixParameters(uriInfo, persistenceUnit);
- Object entityId = IdHelper.buildId(context, type, id);
- Object entity = context.find(discriminators, type, entityId, getQueryParameters(uriInfo));
+ final PersistenceContext context = getPersistenceContext(persistenceUnit, type, uriInfo.getBaseUri(), version, null);
+ final Map<String, String> discriminators = getMatrixParameters(uriInfo, persistenceUnit);
+ final Object entityId = IdHelper.buildId(context, type, id);
+ final Object entity = context.find(discriminators, type, entityId, getQueryParameters(uriInfo));
if (entity == null) {
JPARSLogger.error("jpars_could_not_find_entity_for_key", new Object[] { type, id, persistenceUnit });
throw JPARSException.entityNotFound(type, id, persistenceUnit);
}
+
+ // Fields filtering
+ if (context.getSupportedFeatureSet().isSupported(Feature.FIELDS_FILTERING)) {
+ final FieldsFilteringValidator fieldsFilteringValidator = new FieldsFilteringValidator(context, uriInfo, entity);
+ if (fieldsFilteringValidator.isFeatureApplicable()) {
+ final StreamingOutputMarshaller marshaller = new StreamingOutputMarshaller(context,
+ singleEntityResponse(context, entity, uriInfo),
+ headers.getAcceptableMediaTypes(),
+ fieldsFilteringValidator.getFields());
+ return Response.ok(marshaller).build();
+ }
+ }
+
return Response.ok(new StreamingOutputMarshaller(context, singleEntityResponse(context, entity, uriInfo), headers.getAcceptableMediaTypes())).build();
} catch (Exception ex) {
throw JPARSException.exceptionOccurred(ex);
diff --git a/dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/jpa/rs/util/StreamingOutputMarshaller.java b/dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/jpa/rs/util/StreamingOutputMarshaller.java
index bec047c..6b9bd4d 100644
--- a/dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/jpa/rs/util/StreamingOutputMarshaller.java
+++ b/dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/jpa/rs/util/StreamingOutputMarshaller.java
@@ -1,171 +1,188 @@
-/*******************************************************************************
- * Copyright (c) 2011, 2013 Oracle and/or its affiliates. All rights reserved.
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
- * which accompanies this distribution.
- * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
- * and the Eclipse Distribution License is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- *
- * Contributors:
- * dclarke/tware - initial
- * tware
- ******************************************************************************/
-package org.eclipse.persistence.jpa.rs.util;
-
-import java.beans.PropertyChangeListener;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.ObjectOutputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.util.List;
-
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.StreamingOutput;
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBException;
-import javax.xml.bind.Marshaller;
-
-import org.eclipse.persistence.dynamic.DynamicEntity;
-import org.eclipse.persistence.internal.dynamic.DynamicEntityImpl;
-import org.eclipse.persistence.jaxb.MarshallerProperties;
-import org.eclipse.persistence.jpa.rs.PersistenceContext;
-import org.eclipse.persistence.jpa.rs.exceptions.JPARSException;
-import org.eclipse.persistence.jpa.rs.util.list.ReportQueryResultList;
-import org.eclipse.persistence.jpa.rs.util.xmladapters.LinkAdapter;
-
-/**
- * Simple {@link StreamingOutput} implementation that uses the provided
- * {@link JAXBContext} to marshal the result when requested to either XML or
- * JSON based on the accept media provided.
- *
- * @author dclarke
- * @since EclipseLink 2.4.0
- */
-public class StreamingOutputMarshaller implements StreamingOutput {
- private PersistenceContext context;
- private Object result;
- private MediaType mediaType;
-
- public StreamingOutputMarshaller(PersistenceContext context, Object result, MediaType acceptedType) {
- this.context = context;
- this.result = result;
- this.mediaType = acceptedType;
- }
-
- public StreamingOutputMarshaller(PersistenceContext context, Object result, List<MediaType> acceptedTypes) {
- this(context, result, mediaType(acceptedTypes));
- }
-
- @Override
- public void write(OutputStream output) throws IOException, WebApplicationException {
- if (result instanceof byte[] && this.mediaType.equals(MediaType.APPLICATION_OCTET_STREAM_TYPE)) {
- output.write((byte[]) result);
- output.flush();
- output.close();
- } else if (result instanceof String) {
- OutputStreamWriter writer = new OutputStreamWriter(output);
- writer.write((String) result);
- writer.flush();
- writer.close();
- } else {
- if ((this.context != null && this.context.getJAXBContext() != null && this.result != null) &&
- (this.mediaType.equals(MediaType.APPLICATION_JSON_TYPE) || this.mediaType.equals(MediaType.APPLICATION_XML_TYPE))) {
- try {
- if (result instanceof ReportQueryResultList) {
- if (mediaType == MediaType.APPLICATION_JSON_TYPE) {
- // avoid outer QueryResultList class (outer grouping name) in JSON responses
- context.marshallEntity(((ReportQueryResultList) result).getItems(), mediaType, output);
- } else {
- context.marshallEntity(result, mediaType, output);
- }
- } else {
- context.marshallEntity(result, mediaType, output);
- }
- return;
- } catch (Exception ex) {
- JPARSLogger.exception("jpars_caught_exception", new Object[] {}, ex);
- throw JPARSException.exceptionOccurred(ex);
- }
- }
-
- if (this.mediaType.equals(MediaType.APPLICATION_OCTET_STREAM_TYPE)) {
- // could not marshall, try serializing
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ObjectOutputStream oos = new ObjectOutputStream(baos);
- oos.writeObject(result);
- oos.flush();
- oos.close();
- output.write(baos.toByteArray());
- } else {
- JPARSLogger.error("jpars_could_not_marshal_requested_result_to_requested_type", new Object[] { result });
- throw new WebApplicationException();
- }
- }
- }
-
- /**
- * Identify the preferred {@link MediaType} from the list provided. This
- * will check for JSON string or {@link MediaType} first then XML.
- *
- * @param types
- * List of {@link MediaType} values;
- * @return selected {@link MediaType}
- */
- public static MediaType mediaType(List<MediaType> types) {
- MediaType aMediaType = MediaType.APPLICATION_JSON_TYPE;
- if ((types != null) && (!types.isEmpty())) {
- for (int i = 0; i < types.size(); i++) {
- aMediaType = types.get(i);
- if (aMediaType.isCompatible(MediaType.APPLICATION_JSON_TYPE)) {
- return MediaType.APPLICATION_JSON_TYPE;
- }
- if (aMediaType.isCompatible(MediaType.APPLICATION_XML_TYPE)) {
- return MediaType.APPLICATION_XML_TYPE;
- }
- if (aMediaType.isCompatible(MediaType.APPLICATION_OCTET_STREAM_TYPE)) {
- return MediaType.APPLICATION_OCTET_STREAM_TYPE;
- }
- }
- }
- // An unsupported media type never comes to resource, no need to throw exception here.
- return MediaType.APPLICATION_JSON_TYPE;
- }
-
- public static Marshaller createMarshaller(PersistenceContext context, MediaType mediaType) throws JAXBException {
- Marshaller marshaller = context.getJAXBContext().createMarshaller();
- marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, mediaType.toString());
- marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
- marshaller.setAdapter(new LinkAdapter(context.getBaseURI().toString(), context));
- marshaller.setListener(new Marshaller.Listener() {
- @Override
- public void beforeMarshal(Object source) {
- if (source instanceof DynamicEntity) {
- DynamicEntityImpl sourceImpl = (DynamicEntityImpl) source;
- PropertyChangeListener listener = sourceImpl._persistence_getPropertyChangeListener();
- sourceImpl._persistence_setPropertyChangeListener(null);
- ((DynamicEntity) source).set("self", source);
- sourceImpl._persistence_setPropertyChangeListener(listener);
- }
- }
- });
- return marshaller;
- }
-
- public static MediaType getResponseMediaType(HttpHeaders headers) {
- MediaType mediaType = MediaType.TEXT_PLAIN_TYPE;
- if (headers != null) {
- List<MediaType> accepts = headers.getAcceptableMediaTypes();
- if (accepts != null && accepts.size() > 0) {
- try {
- mediaType = StreamingOutputMarshaller.mediaType(accepts);
- } catch (Exception ex) {
- }
- }
- }
- return mediaType;
- }
-}
+/*******************************************************************************
+ * Copyright (c) 2011, 2013 Oracle and/or its affiliates. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * dclarke/tware - initial
+ * tware
+ ******************************************************************************/
+package org.eclipse.persistence.jpa.rs.util;
+
+import org.eclipse.persistence.dynamic.DynamicEntity;
+import org.eclipse.persistence.internal.dynamic.DynamicEntityImpl;
+import org.eclipse.persistence.jaxb.MarshallerProperties;
+import org.eclipse.persistence.jpa.rs.PersistenceContext;
+import org.eclipse.persistence.jpa.rs.exceptions.JPARSException;
+import org.eclipse.persistence.jpa.rs.util.list.ReportQueryResultList;
+import org.eclipse.persistence.jpa.rs.util.xmladapters.LinkAdapter;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.StreamingOutput;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import java.beans.PropertyChangeListener;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.util.List;
+
+/**
+ * Simple {@link StreamingOutput} implementation that uses the provided
+ * {@link JAXBContext} to marshal the result when requested to either XML or
+ * JSON based on the accept media provided.
+ *
+ * @author dclarke
+ * @since EclipseLink 2.4.0
+ */
+public class StreamingOutputMarshaller implements StreamingOutput {
+ private PersistenceContext context;
+ private Object result;
+ private MediaType mediaType;
+ private List<String> fields;
+
+ public StreamingOutputMarshaller(PersistenceContext context, Object result, MediaType acceptedType) {
+ this.context = context;
+ this.result = result;
+ this.mediaType = acceptedType;
+ }
+
+ /**
+ * This constructor is used for fields filtering. Only attributes included in fields parameter are marshalled.
+ *
+ * @param context persistence context.
+ * @param result entity to process.
+ * @param acceptedTypes
+ * @param fields a list of fields of 'result' entity to marshall.
+ */
+ public StreamingOutputMarshaller(PersistenceContext context, Object result, List<MediaType> acceptedTypes, List<String> fields) {
+ this(context, result, acceptedTypes);
+ this.fields = fields;
+ }
+
+ public StreamingOutputMarshaller(PersistenceContext context, Object result, List<MediaType> acceptedTypes) {
+ this(context, result, mediaType(acceptedTypes));
+ }
+
+ @Override
+ public void write(OutputStream output) throws IOException, WebApplicationException {
+ if (result instanceof byte[] && this.mediaType.equals(MediaType.APPLICATION_OCTET_STREAM_TYPE)) {
+ output.write((byte[]) result);
+ output.flush();
+ output.close();
+ } else if (result instanceof String) {
+ OutputStreamWriter writer = new OutputStreamWriter(output);
+ writer.write((String) result);
+ writer.flush();
+ writer.close();
+ } else {
+ if ((this.context != null && this.context.getJAXBContext() != null && this.result != null) &&
+ (this.mediaType.equals(MediaType.APPLICATION_JSON_TYPE) || this.mediaType.equals(MediaType.APPLICATION_XML_TYPE))) {
+ try {
+ if (result instanceof ReportQueryResultList) {
+ if (mediaType == MediaType.APPLICATION_JSON_TYPE) {
+ // avoid outer QueryResultList class (outer grouping name) in JSON responses
+ context.marshallEntity(((ReportQueryResultList) result).getItems(), mediaType, output);
+ } else {
+ context.marshallEntity(result, mediaType, output);
+ }
+ } else {
+ if (fields != null) {
+ context.marshallEntity(result, fields, mediaType, output);
+ } else {
+ context.marshallEntity(result, mediaType, output);
+ }
+ }
+ return;
+ } catch (Exception ex) {
+ JPARSLogger.exception("jpars_caught_exception", new Object[] {}, ex);
+ throw JPARSException.exceptionOccurred(ex);
+ }
+ }
+
+ if (this.mediaType.equals(MediaType.APPLICATION_OCTET_STREAM_TYPE)) {
+ // could not marshall, try serializing
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject(result);
+ oos.flush();
+ oos.close();
+ output.write(baos.toByteArray());
+ } else {
+ JPARSLogger.error("jpars_could_not_marshal_requested_result_to_requested_type", new Object[] { result });
+ throw new WebApplicationException();
+ }
+ }
+ }
+
+ /**
+ * Identify the preferred {@link MediaType} from the list provided. This
+ * will check for JSON string or {@link MediaType} first then XML.
+ *
+ * @param types
+ * List of {@link MediaType} values;
+ * @return selected {@link MediaType}
+ */
+ public static MediaType mediaType(List<MediaType> types) {
+ MediaType aMediaType = MediaType.APPLICATION_JSON_TYPE;
+ if ((types != null) && (!types.isEmpty())) {
+ for (int i = 0; i < types.size(); i++) {
+ aMediaType = types.get(i);
+ if (aMediaType.isCompatible(MediaType.APPLICATION_JSON_TYPE)) {
+ return MediaType.APPLICATION_JSON_TYPE;
+ }
+ if (aMediaType.isCompatible(MediaType.APPLICATION_XML_TYPE)) {
+ return MediaType.APPLICATION_XML_TYPE;
+ }
+ if (aMediaType.isCompatible(MediaType.APPLICATION_OCTET_STREAM_TYPE)) {
+ return MediaType.APPLICATION_OCTET_STREAM_TYPE;
+ }
+ }
+ }
+ // An unsupported media type never comes to resource, no need to throw exception here.
+ return MediaType.APPLICATION_JSON_TYPE;
+ }
+
+ public static Marshaller createMarshaller(PersistenceContext context, MediaType mediaType) throws JAXBException {
+ Marshaller marshaller = context.getJAXBContext().createMarshaller();
+ marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, mediaType.toString());
+ marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
+ marshaller.setAdapter(new LinkAdapter(context.getBaseURI().toString(), context));
+ marshaller.setListener(new Marshaller.Listener() {
+ @Override
+ public void beforeMarshal(Object source) {
+ if (source instanceof DynamicEntity) {
+ DynamicEntityImpl sourceImpl = (DynamicEntityImpl) source;
+ PropertyChangeListener listener = sourceImpl._persistence_getPropertyChangeListener();
+ sourceImpl._persistence_setPropertyChangeListener(null);
+ ((DynamicEntity) source).set("self", source);
+ sourceImpl._persistence_setPropertyChangeListener(listener);
+ }
+ }
+ });
+ return marshaller;
+ }
+
+ public static MediaType getResponseMediaType(HttpHeaders headers) {
+ MediaType mediaType = MediaType.TEXT_PLAIN_TYPE;
+ if (headers != null) {
+ List<MediaType> accepts = headers.getAcceptableMediaTypes();
+ if (accepts != null && accepts.size() > 0) {
+ try {
+ mediaType = StreamingOutputMarshaller.mediaType(accepts);
+ } catch (Exception ex) {
+ }
+ }
+ }
+ return mediaType;
+ }
+}
diff --git a/jpa/eclipselink.jpars.test/src/org/eclipse/persistence/jpars/test/AllJavaEETests.java b/jpa/eclipselink.jpars.test/src/org/eclipse/persistence/jpars/test/AllJavaEETests.java
index 8aed030..48987f9 100644
--- a/jpa/eclipselink.jpars.test/src/org/eclipse/persistence/jpars/test/AllJavaEETests.java
+++ b/jpa/eclipselink.jpars.test/src/org/eclipse/persistence/jpars/test/AllJavaEETests.java
@@ -16,13 +16,14 @@ package org.eclipse.persistence.jpars.test;
import org.eclipse.persistence.jpars.test.server.ServerCrudTest;
import org.eclipse.persistence.jpars.test.server.ServerEmployeeTest;
import org.eclipse.persistence.jpars.test.server.ServerEmployeeTestV2;
+import org.eclipse.persistence.jpars.test.server.ServerFieldsFilteringTest;
import org.eclipse.persistence.jpars.test.server.ServerPageableTest;
import org.eclipse.persistence.jpars.test.server.ServerTravelerTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(VersionedTestSuite.class)
-@SuiteClasses({ ServerEmployeeTestV2.class, ServerCrudTest.class, ServerEmployeeTest.class, ServerTravelerTest.class, ServerPageableTest.class })
+@SuiteClasses({ ServerEmployeeTestV2.class, ServerCrudTest.class, ServerEmployeeTest.class, ServerTravelerTest.class, ServerPageableTest.class, ServerFieldsFilteringTest.class })
public class AllJavaEETests {
}
diff --git a/jpa/eclipselink.jpars.test/src/org/eclipse/persistence/jpars/test/server/ServerFieldsFilteringTest.java b/jpa/eclipselink.jpars.test/src/org/eclipse/persistence/jpars/test/server/ServerFieldsFilteringTest.java
new file mode 100644
index 0000000..ce8d418
--- /dev/null
+++ b/jpa/eclipselink.jpars.test/src/org/eclipse/persistence/jpars/test/server/ServerFieldsFilteringTest.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Dmitry Kornilov - initial implementation
+ ******************************************************************************/
+package org.eclipse.persistence.jpars.test.server;
+
+import org.eclipse.persistence.config.PersistenceUnitProperties;
+import org.eclipse.persistence.dynamic.DynamicClassLoader;
+import org.eclipse.persistence.jpa.rs.PersistenceContext;
+import org.eclipse.persistence.jpa.rs.PersistenceFactoryBase;
+import org.eclipse.persistence.jpars.test.model.basket.Basket;
+import org.eclipse.persistence.jpars.test.model.basket.BasketItem;
+import org.eclipse.persistence.jpars.test.util.ExamplePropertiesLoader;
+import org.eclipse.persistence.jpars.test.util.RestUtils;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import javax.persistence.Persistence;
+import javax.ws.rs.core.MediaType;
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * This class tests fields filtering feature introduced in V2.
+ *
+ * @author Dmitry Kornilov
+ */
+public class ServerFieldsFilteringTest {
+ private static final Logger logger = Logger.getLogger("org.eclipse.persistence.jpars.test.server");
+
+ private static final String JPA_RS_VERSION_STRING = "jpars.version.string";
+ private static final String DEFAULT_PU = "jpars_basket-static";
+
+ private static PersistenceContext context;
+ private static PersistenceFactoryBase factory;
+
+ @BeforeClass
+ public static void setup() throws Exception {
+ final Map<String, Object> properties = new HashMap<String, Object>();
+ ExamplePropertiesLoader.loadProperties(properties);
+ properties.put(PersistenceUnitProperties.NON_JTA_DATASOURCE, null);
+ properties.put(PersistenceUnitProperties.DDL_GENERATION, PersistenceUnitProperties.DROP_AND_CREATE);
+ properties.put(PersistenceUnitProperties.CLASSLOADER, new DynamicClassLoader(Thread.currentThread().getContextClassLoader()));
+ System.setProperty(JPA_RS_VERSION_STRING, "v2.0");
+ factory = new PersistenceFactoryBase();
+ context = factory.bootstrapPersistenceContext(DEFAULT_PU, Persistence.createEntityManagerFactory(DEFAULT_PU, properties), RestUtils.getServerURI(), null, true);
+ initData();
+ }
+
+ @AfterClass
+ public static void cleanup() throws Exception {
+ try {
+ RestUtils.restUpdateQuery(context, "BasketItem.deleteAll", "BasketItem", null, null, MediaType.APPLICATION_JSON_TYPE);
+ RestUtils.restUpdateQuery(context, "Basket.deleteAll", "Basket", null, null, MediaType.APPLICATION_JSON_TYPE);
+ } catch (URISyntaxException e) {
+ }
+ }
+
+ private static void initData() throws Exception {
+ // Create a basket
+ Basket basket = new Basket();
+ basket.setId(1);
+ basket.setName("Basket1");
+ basket = RestUtils.restCreate(context, basket, Basket.class.getSimpleName(), Basket.class, null, MediaType.APPLICATION_XML_TYPE, true);
+ assertNotNull("Basket create failed.", basket);
+
+ // Add items
+ for (int j=1; j<=5; j++) {
+ BasketItem basketItem = new BasketItem();
+ basketItem.setId(j);
+ basketItem.setName("BasketItem" + j);
+ RestUtils.restUpdate(context, basketItem, BasketItem.class.getSimpleName(), BasketItem.class, null, MediaType.APPLICATION_XML_TYPE, false);
+ RestUtils.restUpdateBidirectionalRelationship(context, String.valueOf(basket.getId()), Basket.class.getSimpleName(), "basketItems", basketItem, MediaType.APPLICATION_XML_TYPE, "basket", true);
+ }
+ }
+
+ @Test
+ public void testFieldsJson() throws URISyntaxException {
+ // fields parameter
+ final Map<String, String> hints = new HashMap<String, String>(1);
+ hints.put("fields", "name,id");
+
+ // Get BasketItem with id = 1
+ String queryResult = RestUtils.restReadWithHints(context, 1, Basket.class.getSimpleName(), hints, MediaType.APPLICATION_JSON_TYPE);
+ logger.info(queryResult);
+
+ // Check that 'name' and 'id' fields are present in the response and other fields are not
+ assertTrue(queryResult.contains("\"id\":1,\"name\":\"Basket1\""));
+ assertFalse(queryResult.contains("\"basketItems\":[\n{"));
+ }
+
+ @Test
+ public void testFieldsXml() throws URISyntaxException {
+ // fields parameter
+ final Map<String, String> hints = new HashMap<String, String>(1);
+ hints.put("fields", "name,id");
+
+ // Get BasketItem with id = 1
+ String queryResult = RestUtils.restReadWithHints(context, 1, Basket.class.getSimpleName(), hints, MediaType.APPLICATION_XML_TYPE);
+ logger.info(queryResult);
+
+ // Check that 'name' and 'id' fields are present in the response and other fields are not
+ assertTrue(queryResult.contains("<id>1</id>"));
+ assertTrue(queryResult.contains("<name>Basket1</name>"));
+ assertFalse(queryResult.contains("<basketItems>"));
+ assertFalse(queryResult.contains("</basketItems>"));
+ }
+
+ @Test
+ public void testExclFieldsJson() throws URISyntaxException {
+ // exclFields parameter
+ final Map<String, String> hints = new HashMap<String, String>(1);
+ hints.put("exclFields", "basketItems,name");
+
+ // Get BasketItem with id = 1
+ String queryResult = RestUtils.restReadWithHints(context, 1, Basket.class.getSimpleName(), hints, MediaType.APPLICATION_JSON_TYPE);
+ logger.info(queryResult);
+
+ // Check that 'name' and 'id' fields are present in the response and other fields are not
+ assertTrue(queryResult.contains("\"id\":1"));
+ assertFalse(queryResult.contains("\"basketItems\":[\n{"));
+ }
+
+ @Test
+ public void testExclFieldsXml() throws URISyntaxException {
+ // exclFields parameter
+ final Map<String, String> hints = new HashMap<String, String>(1);
+ hints.put("exclFields", "basketItems,name");
+
+ // Get BasketItem with id = 1
+ String queryResult = RestUtils.restReadWithHints(context, 1, Basket.class.getSimpleName(), hints, MediaType.APPLICATION_XML_TYPE);
+ logger.info(queryResult);
+
+ // Check that 'name' and 'id' fields are present in the response and other fields are not
+ assertTrue(queryResult.contains("<id>1</id>"));
+ assertFalse(queryResult.contains("<basketItems>"));
+ assertFalse(queryResult.contains("</basketItems>"));
+ }
+}
diff --git a/jpa/eclipselink.jpars.test/src/org/eclipse/persistence/jpars/test/server/ServerPageableTest.java b/jpa/eclipselink.jpars.test/src/org/eclipse/persistence/jpars/test/server/ServerPageableTest.java
index 3e84287..d449aa8 100644
--- a/jpa/eclipselink.jpars.test/src/org/eclipse/persistence/jpars/test/server/ServerPageableTest.java
+++ b/jpa/eclipselink.jpars.test/src/org/eclipse/persistence/jpars/test/server/ServerPageableTest.java
@@ -46,8 +46,8 @@ public class ServerPageableTest {
private static final String JPA_RS_VERSION_STRING = "jpars.version.string";
private static final String DEFAULT_PU = "jpars_basket-static";
- private static PersistenceContext context = null;
- private static PersistenceFactoryBase factory = null;
+ private static PersistenceContext context;
+ private static PersistenceFactoryBase factory;
@BeforeClass
public static void setup() throws Exception {
diff --git a/jpa/eclipselink.jpars.test/src/org/eclipse/persistence/jpars/test/util/RestUtils.java b/jpa/eclipselink.jpars.test/src/org/eclipse/persistence/jpars/test/util/RestUtils.java
index 0c297aa..6bf40a6 100644
--- a/jpa/eclipselink.jpars.test/src/org/eclipse/persistence/jpars/test/util/RestUtils.java
+++ b/jpa/eclipselink.jpars.test/src/org/eclipse/persistence/jpars/test/util/RestUtils.java
@@ -161,10 +161,34 @@ public class RestUtils {
uri.append(RestUtils.getServerURI() + context.getName());
if (tenantId != null) {
for (String key : tenantId.keySet()) {
- uri.append(";" + key + "=" + tenantId.get(key));
+ uri.append(";").append(key).append("=").append(tenantId.get(key));
}
}
- uri.append("/entity/" + type + "/" + id);
+ uri.append("/entity/").append(type).append("/").append(id);
+ WebResource webResource = client.resource(uri.toString());
+ ClientResponse response = webResource.accept(outputMediaType).get(ClientResponse.class);
+ Status status = response.getClientResponseStatus();
+ String result = response.getEntity(String.class);
+ if (status != Status.OK) {
+ restCallFailed(context, status, result, outputMediaType);
+ }
+ return result;
+ }
+
+ /**
+ * REST GET entity with hints.
+ *
+ * @param context persistent context
+ * @param id entity ID
+ * @param type entity type
+ * @param hints hints list
+ * @param outputMediaType media type
+ * @return response in string
+ */
+ public static String restReadWithHints(PersistenceContext context, Object id, String type, Map<String, String> hints, MediaType outputMediaType) throws RestCallFailedException, URISyntaxException {
+ StringBuilder uri = new StringBuilder();
+ uri.append(RestUtils.getServerURI()).append(context.getName()).append("/entity/").append(type).append("/").append(id);
+ appendParametersAndHints(uri, null, hints);
WebResource webResource = client.resource(uri.toString());
ClientResponse response = webResource.accept(outputMediaType).get(ClientResponse.class);
Status status = response.getClientResponseStatus();