Add some metadata services
diff --git a/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/PersistenceContext.java b/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/PersistenceContext.java
index d9347c5..b94173c 100644
--- a/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/PersistenceContext.java
+++ b/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/PersistenceContext.java
@@ -17,6 +17,7 @@
import java.io.IOException;
import java.io.InputStream;
+import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
@@ -79,6 +80,8 @@
private EntityManagerFactory emf;
private JAXBContext context = null;
+
+ private URI baseURI = null;
public PersistenceContext(Archive archive, Map<String, Object> properties, ClassLoader classLoader){
super();
@@ -154,6 +157,14 @@
return context;
}
+ public URI getBaseURI() {
+ return baseURI;
+ }
+
+ public void setBaseURI(URI baseURI) {
+ this.baseURI = baseURI;
+ }
+
public void create(String tenantId, DynamicEntity entity) {
EntityManager em = getEmf().createEntityManager();
diff --git a/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/PersistenceFactory.java b/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/PersistenceFactory.java
index 430bca0..839c961 100644
--- a/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/PersistenceFactory.java
+++ b/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/PersistenceFactory.java
@@ -19,6 +19,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import javax.ejb.Singleton;
@@ -86,7 +87,6 @@
public PersistenceContext bootstrapPersistenceContext(String name, Archive archive, String persistenceXMLLocation, Map<String, ?> originalProperties, boolean replace){
- System.out.println("--- bootstrap persitence context " + name + " - " + persistenceXMLLocation);
initialize();
PersistenceContext persistenceContext = getPersistenceContext(name);
if (persistenceContext == null || replace){
@@ -110,6 +110,10 @@
return persistenceContexts.get(name);
}
+ public Set<String> getPersistenceContextNames(){
+ return persistenceContexts.keySet();
+ }
+
public void closePersistenceContext(String name){
PersistenceContext context = persistenceContexts.get(name);
if (context != null){
diff --git a/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/Service.java b/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/Service.java
index d5aead0..309cb8a 100644
--- a/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/Service.java
+++ b/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/Service.java
@@ -16,11 +16,14 @@
import static org.eclipse.persistence.jpa.rs.util.StreamingOutputMarshaller.mediaType;
import java.io.InputStream;
+import java.net.URI;
import java.net.URL;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Set;
import java.util.logging.Logger;
import javax.annotation.PreDestroy;
@@ -30,6 +33,7 @@
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
+import javax.ws.rs.DELETE;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
@@ -42,6 +46,7 @@
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.StreamingOutput;
+import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
@@ -49,7 +54,9 @@
import javax.xml.transform.stream.StreamSource;
import org.eclipse.persistence.config.PersistenceUnitProperties;
+import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.dynamic.DynamicEntity;
+import org.eclipse.persistence.jpa.JpaHelper;
import org.eclipse.persistence.jpa.rs.metadata.DatabaseMetadataStore;
import org.eclipse.persistence.jpa.rs.util.IdHelper;
import org.eclipse.persistence.jpa.rs.util.LinkAdapter;
@@ -64,8 +71,8 @@
* @since EclipseLink 2.4.0
*/
@Singleton
-@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Path("/")
public class Service {
static final Logger logger = Logger.getLogger("AppService");
@@ -81,8 +88,9 @@
this.factory = factory;
}
- @POST
+ @PUT
@Path("/")
+ @Consumes({ MediaType.WILDCARD})
public Response start(@PathParam("context") String persistenceUnit, @PathParam("type") String type, @Context HttpHeaders hh, InputStream in){
ResponseBuilder rb = new ResponseBuilderImpl();
try{
@@ -101,9 +109,30 @@
return rb.build();
}
- @POST
+ @GET
+ @Path("/")
+ @Consumes({ MediaType.WILDCARD})
+ public Response getContexts(@Context HttpHeaders hh) {
+ ResponseBuilder rb = new ResponseBuilderImpl();
+ Set<String> contexts = factory.getPersistenceContextNames();
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("[");
+ Iterator<String> contextIterator = contexts.iterator();
+ while (contextIterator.hasNext()){
+ buffer.append("\"" + contextIterator.next() + "\"");
+ if (contextIterator.hasNext()){
+ buffer.append(", ");
+ }
+ }
+ buffer.append("]");
+ rb.status(Status.OK);
+ rb.entity(new StreamingOutputMarshaller(null, buffer.toString(), hh.getAcceptableMediaTypes()));
+ return rb.build();
+ }
+
+ @PUT
@Path("{context}")
- public Response bootstrap(@PathParam("context") String persistenceUnit, @PathParam("type") String type, @Context HttpHeaders hh, InputStream in){
+ public Response bootstrap(@PathParam("context") String persistenceUnit, @PathParam("type") String type, @Context HttpHeaders hh, @Context UriInfo uriInfo, InputStream in){
ResponseBuilder rb = new ResponseBuilderImpl();
String urlString = getURL(hh);
PersistenceContext persistenceContext = null;
@@ -120,11 +149,50 @@
persistenceContext = factory.bootstrapPersistenceContext(persistenceUnit, in, new HashMap<String, Object>(), replace);
}
} catch (Exception e){
+ e.printStackTrace();
rb.status(Status.NOT_FOUND);
}
if (persistenceContext != null){
+ persistenceContext.setBaseURI(uriInfo.getBaseUri());
rb.status(Status.CREATED);
}
+
+ return rb.build();
+ }
+
+ @GET
+ @Path("{context}")
+ @Consumes({ MediaType.WILDCARD})
+ public Response getTypes(@PathParam("context") String persistenceUnit, @Context HttpHeaders hh) {
+ ResponseBuilder rb = new ResponseBuilderImpl();
+ PersistenceContext app = get(persistenceUnit);
+ if (app == null){
+ rb.status(Status.NOT_FOUND);
+ } else {
+ Map<Class, ClassDescriptor> descriptors = JpaHelper.getServerSession(app.getEmf()).getDescriptors();
+ StringBuffer buffer = new StringBuffer();
+
+ buffer.append("[");
+ Iterator<Class> contextIterator = descriptors.keySet().iterator();
+ while (contextIterator.hasNext()){
+ buffer.append("\"" + descriptors.get(contextIterator.next()).getAlias() + "\"");
+ if (contextIterator.hasNext()){
+ buffer.append(", ");
+ }
+ }
+ buffer.append("]");
+ rb.status(Status.OK);
+ rb.entity(new StreamingOutputMarshaller(null , buffer.toString(), hh.getAcceptableMediaTypes()));
+ }
+ return rb.build();
+ }
+
+ @DELETE
+ @Path("{context}")
+ public Response removeContext(@PathParam("context") String persistenceUnit, @PathParam("type") String type, @Context HttpHeaders hh, InputStream in){
+ ResponseBuilder rb = new ResponseBuilderImpl();
+ factory.closePersistenceContext(persistenceUnit);
+ rb.status(Status.OK);
return rb.build();
}
@@ -234,7 +302,7 @@
try {
unmarshaller = app.getJAXBContext().createUnmarshaller();
unmarshaller.setProperty(MEDIA_TYPE, acceptedMedia.toString());
- unmarshaller.setAdapter(new LinkAdapter("http://localhost:8080/JPA-RS/auction/entity/", app));
+ unmarshaller.setAdapter(new LinkAdapter(app.getBaseURI().toString(), app));
JAXBElement<?> element = unmarshaller.unmarshal(new StreamSource(in), app.getClass(type));
return (DynamicEntity) element.getValue();
} catch (JAXBException e) {
diff --git a/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/util/LinkAdapter.java b/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/util/LinkAdapter.java
index c11d6d1..a8e7a96 100644
--- a/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/util/LinkAdapter.java
+++ b/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/util/LinkAdapter.java
@@ -34,7 +34,7 @@
public class LinkAdapter extends XmlAdapter<String, Object> {
- private String baseURI = "http://example.com/DEFAULT/";
+ private String baseURI = null;
protected PersistenceContext context;
public LinkAdapter() {
@@ -44,7 +44,7 @@
this.baseURI = baseURI;
this.context = context;
}
-
+
@Override
@SuppressWarnings("rawtypes")
// TODO Composite keys
@@ -53,7 +53,7 @@
return null;
}
int lastSlash = v.lastIndexOf('/');
- String entityType = v.substring(baseURI.length(), lastSlash);
+ String entityType = v.substring((baseURI + context.getName() + "/" ).length(), lastSlash);
String entityId = v.substring(lastSlash + 1);
ClassDescriptor descriptor = context.getDescriptor(entityType);
DatabaseMapping idMapping = getIdMapping(descriptor);
@@ -102,7 +102,7 @@
return "";
}
Object id = de.get(idMapping.getAttributeName());
- String href = baseURI + v.getClass().getSimpleName() + "/"
+ String href = baseURI + context.getName() + "/" + v.getClass().getSimpleName() + "/"
+ id;
return href;
}
diff --git a/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/util/StreamingOutputMarshaller.java b/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/util/StreamingOutputMarshaller.java
index 5cf649a..4f6827f 100644
--- a/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/util/StreamingOutputMarshaller.java
+++ b/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/util/StreamingOutputMarshaller.java
@@ -16,12 +16,12 @@
import static org.eclipse.persistence.jaxb.JAXBContext.MEDIA_TYPE;
import java.beans.PropertyChangeListener;
+import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
-import java.io.StringWriter;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
@@ -63,22 +63,9 @@
}
public void write(OutputStream output) throws IOException, WebApplicationException {
- if (this.context.getJAXBContext() != null && this.result != null && !this.mediaType.equals(MediaType.WILDCARD_TYPE)) {
+ if (this.context != null && this.context.getJAXBContext() != null && this.result != null && !this.mediaType.equals(MediaType.WILDCARD_TYPE)) {
try {
- Marshaller marshaller = this.context.getJAXBContext().createMarshaller();
- marshaller.setProperty(MEDIA_TYPE, this.mediaType.toString());
- marshaller.setProperty(org.eclipse.persistence.jaxb.JAXBContext.INCLUDE_ROOT, false);
- marshaller.setAdapter(new LinkAdapter("http://localhost:8080/JPA-RS/auction/entity/", context));
- marshaller.setListener(new Marshaller.Listener() {
- @Override
- public void beforeMarshal(Object source) {
- DynamicEntityImpl sourceImpl = (DynamicEntityImpl)source;
- PropertyChangeListener listener = sourceImpl._persistence_getPropertyChangeListener();
- sourceImpl._persistence_setPropertyChangeListener(null);
- ((DynamicEntity)source).set("self", source);
- sourceImpl._persistence_setPropertyChangeListener(listener);
- }
- });
+ Marshaller marshaller = createMarshaller(context, mediaType);
if (result instanceof Collection) {
@SuppressWarnings("unchecked")
Collection<Object> objs = (Collection<Object>) result;
@@ -117,6 +104,11 @@
}
} else if (result instanceof byte[]){
output.write((byte[])result);
+ } else if (result instanceof String){
+ OutputStreamWriter writer = new OutputStreamWriter(output);
+ writer.write((String)result);
+ writer.flush();
+ writer.close();
} else {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
@@ -126,7 +118,7 @@
output.write(baos.toByteArray());
}
}
-
+
/**
* Identify the preferred {@link MediaType} from the list provided. This
* will check for JSON string or {@link MediaType} first then XML.
@@ -160,4 +152,22 @@
}
return false;
}
+
+ public static Marshaller createMarshaller(PersistenceContext context, MediaType mediaType) throws JAXBException{
+ Marshaller marshaller = context.getJAXBContext().createMarshaller();
+ marshaller.setProperty(MEDIA_TYPE, mediaType.toString());
+ marshaller.setProperty(org.eclipse.persistence.jaxb.JAXBContext.INCLUDE_ROOT, false);
+ marshaller.setAdapter(new LinkAdapter(context.getBaseURI().toString(), context));
+ marshaller.setListener(new Marshaller.Listener() {
+ @Override
+ public void beforeMarshal(Object source) {
+ DynamicEntityImpl sourceImpl = (DynamicEntityImpl)source;
+ PropertyChangeListener listener = sourceImpl._persistence_getPropertyChangeListener();
+ sourceImpl._persistence_setPropertyChangeListener(null);
+ ((DynamicEntity)source).set("self", source);
+ sourceImpl._persistence_setPropertyChangeListener(listener);
+ }
+ });
+ return marshaller;
+ }
}
diff --git a/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/websockets/JPARSWebSocket.java b/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/websockets/JPARSWebSocket.java
index 601aaf8..6a865c6 100644
--- a/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/websockets/JPARSWebSocket.java
+++ b/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/websockets/JPARSWebSocket.java
@@ -28,6 +28,7 @@
import org.eclipse.persistence.jpa.rs.PersistenceContext;
import org.eclipse.persistence.jpa.rs.util.LinkAdapter;
+import org.eclipse.persistence.jpa.rs.util.StreamingOutputMarshaller;
import com.sun.grizzly.websockets.DataFrame;
import com.sun.grizzly.websockets.DefaultWebSocket;
@@ -114,21 +115,7 @@
protected String marshallEntity(PersistenceContext context, Object entity) {
try {
- JAXBContext jaxbContext = context.getJAXBContext();
- Marshaller marshaller = jaxbContext.createMarshaller();
- marshaller.setProperty(MEDIA_TYPE, MediaType.APPLICATION_JSON);
- marshaller.setProperty(org.eclipse.persistence.jaxb.JAXBContext.INCLUDE_ROOT, false);
- marshaller.setAdapter(new LinkAdapter("http://localhost:8080/JPA-RS/auction/entity/", context));
- marshaller.setListener(new Marshaller.Listener() {
- @Override
- public void beforeMarshal(Object source) {
- DynamicEntityImpl sourceImpl = (DynamicEntityImpl)source;
- PropertyChangeListener listener = sourceImpl._persistence_getPropertyChangeListener();
- sourceImpl._persistence_setPropertyChangeListener(null);
- ((DynamicEntity)source).set("self", source);
- sourceImpl._persistence_setPropertyChangeListener(listener);
- }
- });
+ Marshaller marshaller = StreamingOutputMarshaller.createMarshaller(context, MediaType.APPLICATION_JSON_TYPE);
StringWriter stringWriter = new StringWriter();
marshaller.marshal(entity, stringWriter);
diff --git a/JPA-RS Incubator/tests/JPA-RS Tests/src/jpars/test/service/TestService.java b/JPA-RS Incubator/tests/JPA-RS Tests/src/jpars/test/service/TestService.java
index 6d615df..cfde8e6 100644
--- a/JPA-RS Incubator/tests/JPA-RS Tests/src/jpars/test/service/TestService.java
+++ b/JPA-RS Incubator/tests/JPA-RS Tests/src/jpars/test/service/TestService.java
@@ -21,6 +21,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
+import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
@@ -53,6 +54,7 @@
import org.eclipse.persistence.jpa.rs.Service;
import org.eclipse.persistence.jpa.rs.metadata.DatabaseMetadataStore;
import org.eclipse.persistence.jpa.rs.util.LinkAdapter;
+import org.eclipse.persistence.jpa.rs.util.StreamingOutputMarshaller;
import org.eclipse.persistence.sessions.server.ServerSession;
import org.junit.AfterClass;
import org.junit.BeforeClass;
@@ -81,9 +83,12 @@
factory.setMetadataStore(new DatabaseMetadataStore());
factory.getMetadataStore().setProperties(properties);
factory.getMetadataStore().clearMetadata();
- factory.bootstrapPersistenceContext("auction", new URL("file:///C:/EclipseLinkView2/incubator/JPA-RS Incubator/tests/JPA-RS Tests/src/xmldocs/auction-persistence.xml"), properties, true);
- factory.bootstrapPersistenceContext("phonebook", new URL("file:///C:/EclipseLinkView2/incubator/JPA-RS Incubator/tests/JPA-RS Tests/src/xmldocs/phonebook-persistence.xml"), properties, true);
-
+ PersistenceContext context = factory.bootstrapPersistenceContext("auction", new URL("file:///C:/EclipseLinkView2/incubator/JPA-RS Incubator/tests/JPA-RS Tests/src/xmldocs/auction-persistence.xml"), properties, true);
+ context.setBaseURI(new URI("http://localhost:8080/JPA-RS/"));
+
+ context = factory.bootstrapPersistenceContext("phonebook", new URL("file:///C:/EclipseLinkView2/incubator/JPA-RS Incubator/tests/JPA-RS Tests/src/xmldocs/phonebook-persistence.xml"), properties, true);
+ context.setBaseURI(new URI("http://localhost:8080/JPA-RS/"));
+
clearData();
} catch (Exception e){
fail(e.toString());
@@ -226,6 +231,8 @@
factory.setMetadataStore(new DatabaseMetadataStore());
factory.getMetadataStore().setProperties(properties);
factory.initialize(properties);
+ factory.getPersistenceContext("auction").setBaseURI(new URI("http://localhost:8080/JPA-RS/"));
+ factory.getPersistenceContext("phonebook").setBaseURI(new URI("http://localhost:8080/JPA-RS/"));
} catch (Exception e){
fail(e.toString());
}
@@ -354,12 +361,30 @@
assertTrue("Laptop was not in results.", resultString.contains("\"description\" : \"Speedy\""));
}
+ @Test
+ public void testMetadataQuery(){
+ Service service = new Service();
+ service.setPersistenceFactory(factory);
+ StreamingOutput output = (StreamingOutput)service.getContexts(generateHTTPHeader(MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON)).getEntity();
+ String result = stringifyResults(output);
+ assertTrue("auction was not in the results", result.contains("auction"));
+ assertTrue("phonebook was not in the results", result.contains("phonebook"));
+
+ output = (StreamingOutput)service.getTypes("auction", generateHTTPHeader(MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON)).getEntity();
+ result = stringifyResults(output);
+
+ assertTrue("Bid was not in the results", result.contains("Bid"));
+ assertTrue("Auction was not in the results", result.contains("Auction"));
+ assertTrue("User was not in the results", result.contains("User"));
+
+ }
+
private static DynamicEntity unmarshalEntity(PersistenceContext app, String type, String tenantId, String acceptedMedia, InputStream in) {
Unmarshaller unmarshaller;
try {
unmarshaller = app.getJAXBContext().createUnmarshaller();
unmarshaller.setProperty(MEDIA_TYPE, acceptedMedia);
- unmarshaller.setAdapter(new LinkAdapter("http://localhost:8080/JPA-RS/auction/entity/", app));
+ unmarshaller.setAdapter(new LinkAdapter(app.getBaseURI().toString(), app));
JAXBElement<?> element = unmarshaller.unmarshal(new StreamSource(in), app.getClass(type));
return (DynamicEntity) element.getValue();
} catch (JAXBException e) {
@@ -394,7 +419,7 @@
}
);
marshaller.setProperty("eclipselink.media-type", mediaType);
- marshaller.setAdapter(new LinkAdapter("http://localhost:8080/JPA-RS/auction/entity/", context));
+ marshaller.setAdapter(new LinkAdapter(context.getBaseURI().toString(), context));
marshaller.setProperty(JAXBContext.INCLUDE_ROOT, Boolean.FALSE);
marshaller.marshal(object, writer);
} catch (Exception e){
@@ -415,4 +440,5 @@
return headers;
}
+
}