| /******************************************************************************* |
| * 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. |
| * |
| * |
| ******************************************************************************/ |
| package org.eclipse.persistence.jpa.rs.resources.common; |
| |
| import java.io.StringWriter; |
| import java.net.URI; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.ServiceLoader; |
| |
| import javax.ws.rs.core.PathSegment; |
| import javax.ws.rs.core.UriInfo; |
| import javax.xml.bind.JAXBElement; |
| import javax.xml.bind.JAXBException; |
| import javax.xml.bind.Marshaller; |
| import javax.xml.namespace.QName; |
| |
| import org.eclipse.persistence.descriptors.ClassDescriptor; |
| import org.eclipse.persistence.internal.jpa.rs.metadata.model.Attribute; |
| import org.eclipse.persistence.internal.jpa.rs.metadata.model.Descriptor; |
| import org.eclipse.persistence.internal.jpa.rs.metadata.model.Link; |
| import org.eclipse.persistence.internal.jpa.rs.metadata.model.LinkTemplate; |
| import org.eclipse.persistence.internal.jpa.rs.metadata.model.PersistenceUnit; |
| import org.eclipse.persistence.internal.jpa.rs.metadata.model.Query; |
| import org.eclipse.persistence.internal.queries.ReportItem; |
| import org.eclipse.persistence.jaxb.JAXBContext; |
| import org.eclipse.persistence.jaxb.JAXBContextFactory; |
| import org.eclipse.persistence.jaxb.MarshallerProperties; |
| import org.eclipse.persistence.jpa.rs.MatrixParameters; |
| import org.eclipse.persistence.jpa.rs.PersistenceContext; |
| import org.eclipse.persistence.jpa.rs.PersistenceContextFactory; |
| import org.eclipse.persistence.jpa.rs.PersistenceContextFactoryProvider; |
| import org.eclipse.persistence.jpa.rs.QueryParameters; |
| import org.eclipse.persistence.jpa.rs.util.JPARSLogger; |
| import org.eclipse.persistence.jpa.rs.util.list.LinkList; |
| import org.eclipse.persistence.jpa.rs.util.list.QueryList; |
| import org.eclipse.persistence.mappings.DatabaseMapping; |
| |
| /** |
| * @author gonural |
| * |
| */ |
| |
| public abstract class AbstractResource { |
| public static final String SERVICE_VERSION_FORMAT = "v\\d\\.\\d"; |
| protected PersistenceContextFactory factory; |
| |
| public static final String SERVICE_VERSION_1_0 = "v1.0"; |
| |
| /** |
| * Sets the persistence factory. |
| * |
| * @param factory the new persistence factory |
| */ |
| public void setPersistenceFactory(PersistenceContextFactory factory) { |
| this.factory = factory; |
| } |
| |
| /** |
| * Gets the persistence factory. |
| * |
| * @return the persistence factory |
| */ |
| public PersistenceContextFactory getPersistenceFactory() { |
| return getPersistenceFactory(Thread.currentThread().getContextClassLoader()); |
| } |
| /** |
| * Gets the persistence factory. |
| * |
| * @return the persistence factory |
| */ |
| public PersistenceContextFactory getPersistenceFactory(ClassLoader loader) { |
| if (factory == null) { |
| factory = buildPersistenceContextFactory(loader); |
| } |
| return factory; |
| } |
| |
| protected PersistenceContextFactory buildPersistenceContextFactory(ClassLoader loader){ |
| ServiceLoader<PersistenceContextFactoryProvider> contextFactoryLoader = ServiceLoader.load(PersistenceContextFactoryProvider.class, loader); |
| |
| for (PersistenceContextFactoryProvider provider: contextFactoryLoader){ |
| PersistenceContextFactory factory = provider.getPersistenceContextFactory(null); |
| if (factory != null){ |
| return factory; |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Get a map of the matrix parameters associated with the URI path segment of the current request |
| * |
| * In JPA-RS, things that user sets (such as parameters of named queries, etc.) are treated as matrix parameters |
| * List of valid matrix parameters for JPA-RS is defined in MatrixParameters |
| * @see MatrixParameters |
| * |
| * @param info the info |
| * @param segment the segment |
| * @return the matrix parameters |
| * |
| */ |
| protected static Map<String, String> getMatrixParameters(UriInfo info, String segment) { |
| Map<String, String> matrixParameters = new HashMap<String, String>(); |
| for (PathSegment pathSegment : info.getPathSegments()) { |
| if (pathSegment.getPath() != null && pathSegment.getPath().equals(segment)) { |
| for (Entry<String, List<String>> entry : pathSegment.getMatrixParameters().entrySet()) { |
| matrixParameters.put(entry.getKey(), entry.getValue().get(0)); |
| } |
| return matrixParameters; |
| } |
| } |
| return matrixParameters; |
| } |
| |
| /** |
| * Get the URI query parameters of the current request |
| * |
| * In JPA-RS, predefined attributes (such as eclipselink query hints) are treated as query parameters |
| * List of valid query parameters for JPA-RS is defined in QueryParameters |
| * @see QueryParameters |
| * |
| * @param info the info |
| * @return the query parameters |
| * |
| */ |
| protected static Map<String, Object> getQueryParameters(UriInfo info) { |
| Map<String, Object> queryParameters = new HashMap<String, Object>(); |
| for (String key : info.getQueryParameters().keySet()) { |
| queryParameters.put(key, info.getQueryParameters().getFirst(key)); |
| } |
| return queryParameters; |
| } |
| |
| /** |
| * Creates the shell jaxb element list. |
| * |
| * @param reportItems the report items |
| * @return the list |
| */ |
| @SuppressWarnings({ "rawtypes", "unchecked" }) |
| protected List<JAXBElement> createShellJAXBElementList(List<ReportItem> reportItems, Object record) { |
| List<JAXBElement> jaxbElements = new ArrayList<JAXBElement>(reportItems.size()); |
| if ((reportItems != null) && (reportItems.size() > 0)) { |
| for (int index = 0; index < reportItems.size(); index++) { |
| ReportItem reportItem = reportItems.get(index); |
| Object reportItemValue = record; |
| if (record instanceof Object[]) { |
| reportItemValue = ((Object[]) record)[index]; |
| } |
| Class reportItemValueType = null; |
| if (reportItemValue != null) { |
| reportItemValueType = reportItemValue.getClass(); |
| if (reportItemValueType == null) { |
| // try other paths to determine the type of the report item |
| DatabaseMapping dbMapping = reportItem.getMapping(); |
| if (dbMapping != null) { |
| reportItemValueType = dbMapping.getAttributeClassification(); |
| } else { |
| ClassDescriptor desc = reportItem.getDescriptor(); |
| if (desc != null) { |
| reportItemValueType = desc.getJavaClass(); |
| } |
| } |
| } |
| |
| // so, we couldn't determine the type of the report item, stop here... |
| if (reportItemValueType == null) { |
| return null; |
| } |
| |
| JAXBElement element = new JAXBElement(new QName(reportItem.getName()), reportItemValueType, reportItemValue); |
| jaxbElements.add(reportItem.getResultIndex(), element); |
| } |
| } |
| } |
| return jaxbElements; |
| } |
| |
| |
| protected static boolean isValidVersion(String version) { |
| if ((version == null) || (SERVICE_VERSION_1_0.equals(version))) { |
| return true; |
| } |
| return false; |
| } |
| |
| protected PersistenceContext getPersistenceContext(String persistenceUnit, URI baseURI, String version, Map<String, Object> initializationProperties) { |
| if (!isValidVersion(version)) { |
| JPARSLogger.fine("unsupported_service_version_in_the_request", new Object[] { version }); |
| throw new IllegalArgumentException(); |
| } |
| |
| return getPersistenceFactory().get(persistenceUnit, baseURI, version, initializationProperties); |
| } |
| |
| protected String getRelationshipPartner(Map<String, String> matrixParams, Map<String, Object> queryParams) { |
| String partner = null; |
| // Fix for Bug 396791 - JPA-RS: partner should be treated as a query parameter |
| // |
| // For backwards compatibility, we check both, matrix and query parameters. |
| if ((queryParams != null) && (!queryParams.isEmpty())) { |
| partner = (String) queryParams.get(QueryParameters.JPARS_RELATIONSHIP_PARTNER); |
| } |
| |
| if (partner == null) { |
| if ((matrixParams != null) && (!matrixParams.isEmpty())) { |
| partner = (String) matrixParams.get(MatrixParameters.JPARS_RELATIONSHIP_PARTNER); |
| } |
| } |
| return partner; |
| } |
| |
| protected String marshallMetadata(Object metadata, String mediaType) throws JAXBException { |
| Class<?>[] jaxbClasses = new Class[] { Link.class, Attribute.class, Descriptor.class, LinkTemplate.class, PersistenceUnit.class, Query.class, LinkList.class, QueryList.class }; |
| JAXBContext context = (JAXBContext) JAXBContextFactory.createContext(jaxbClasses, null); |
| Marshaller marshaller = context.createMarshaller(); |
| marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, Boolean.FALSE); |
| marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, mediaType); |
| marshaller.setProperty(MarshallerProperties.JSON_REDUCE_ANY_ARRAYS, true); |
| |
| StringWriter writer = new StringWriter(); |
| marshaller.marshal(metadata, writer); |
| return writer.toString(); |
| } |
| |
| } |