Skip to content

Commit

Permalink
v1.3: support plugin external storage service for blog persistent
Browse files Browse the repository at this point in the history
  • Loading branch information
greenlaw110 committed Jun 20, 2013
1 parent b5cd4ad commit cab2016
Show file tree
Hide file tree
Showing 101 changed files with 4,201 additions and 404 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -11,3 +11,4 @@ lib
.dbshell
*.iml
*.eml
*.ipl
45 changes: 45 additions & 0 deletions app/controllers/BlobViewer.java
@@ -0,0 +1,45 @@
package controllers;

import com.greenlaw110.storage.ISObject;
import com.greenlaw110.util.F;
import com.greenlaw110.util.S;
import play.cache.Cache;
import play.modules.morphia.Blob;
import play.modules.morphia.BlobStorageService;
import play.mvc.Controller;

/**
* A generic blob viewer
*/
public class BlobViewer extends Controller {
public static void view(String key) {
notFoundIfNull(key);
Blob blob;
if (key.endsWith(Blob.TMP_ID_SUFFIX)) {
blob = Cache.get(key, Blob.class);
notFoundIfNull(blob);
} else {
if (!key.contains("-")) {
ISObject sobj = Cache.get(key, ISObject.class);
notFoundIfNull(sobj);
response.setContentTypeIfNotSet(sobj.getAttribute(ISObject.ATTR_CONTENT_TYPE));
renderBinary(sobj.asInputStream());
}
F.Str s = S.str(key);
String ssKey = s.afterLast("-").get();
BlobStorageService bss = BlobStorageService.getService(ssKey);
String objKey = s.beforeFirst("-").get();
ISObject sobj = bss.get(objKey);
if (null == objKey) {
sobj = Cache.get(key, ISObject.class);
}
notFoundIfNull(sobj);
blob = new Blob(sobj, bss);
}
if (!blob.exists()) {
notFound();
}
response.setContentTypeIfNotSet(blob.type());
renderBinary(blob.get());
}
}
12 changes: 6 additions & 6 deletions app/morphia/Filter.java
@@ -1,10 +1,10 @@
package morphia;

import com.greenlaw110.util.S;

import java.util.ArrayList;
import java.util.List;

import play.modules.morphia.utils.StringUtil;

public class Filter {

public static class Option {
Expand Down Expand Up @@ -40,8 +40,8 @@ public String toString() {
if (o.checked)
selected.add(o.name);
}
return selected.size() == 0 ? "" : String.format("%1$s in (%2$s)",
property, StringUtil.join(",", selected));
return selected.size() == 0 ? "" : S.fmt("%1$s in (%2$s)",
property, S.join(",", selected));
}

public static String toString(List<Filter> filters) {
Expand All @@ -50,10 +50,10 @@ public static String toString(List<Filter> filters) {
List<String> l = new ArrayList<String>();
for (Filter f : filters) {
String s = f.toString();
if (!StringUtil.isEmpty(s))
if (!S.empty(s))
l.add(s);
}
return null == filters ? null : StringUtil.join(" and ", l);
return null == filters ? null : S.join(" and ", l);
}

}
2 changes: 2 additions & 0 deletions bm.bat
Expand Up @@ -4,4 +4,6 @@ rm -rf target
find samples-and-tests -name tmp | xargs rm -rf
find samples-and-tests -name precompiled | xargs rm -rf
find samples-and-tests -name modules | xargs rm -rf
find samples-and-tests -name lib | xargs rm -rf

play build-module
3 changes: 2 additions & 1 deletion conf/dependencies.yml
@@ -1,4 +1,5 @@
# History
# 1.3 - new blob handling logic, enable external storage (e.g. S3) in addition to gridfs
# 1.2.15a - improve Blob handling
# 1.2.15 - Add <code>isDeleted()</code> method to <code>Model</code> class
# - "new Blob() should not save the content into gridfs":https://github.com/greenlaw110/play-morphia/issues/107
Expand Down Expand Up @@ -29,6 +30,6 @@
# - trim value when processing where statement in Factory.fetch
# 1.2.5 - mavenize project
# 1.2.4d - Add BlobGsonAdapter and ModelFactoryGsonAdapter utilities
self: play -> morphia 1.2.15a
self: play -> morphia 1.3
require:
- play 1.2
1 change: 1 addition & 0 deletions conf/routes
@@ -0,0 +1 @@
GET /blob/{id} BlobViewer.view
4 changes: 4 additions & 0 deletions documentation/manual/history.textile
Expand Up @@ -4,6 +4,10 @@ h2. <a name="roadmap">TODO list</a>

* MongoDB multi-tenant support

h2. <a name="1.3">Updates in 1.3</a>

* "Support external storage in addition to GridFS":https://github.com/greenlaw110/play-morphia/issues/110

h2. <a name="1.2.15a">Updates in 1.2.15a</a>

* Add @isDeleted()@ method to @Model@ class
Expand Down
8 changes: 8 additions & 0 deletions samples-and-tests/album/album.ipr
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/album.iml" filepath="$PROJECT_DIR$/album.iml" />
</modules>
</component>
</project>
85 changes: 85 additions & 0 deletions samples-and-tests/album/app/controllers/Application.java
@@ -0,0 +1,85 @@
package controllers;

import models.Album;
import models.Photo;
import play.cache.Cache;
import play.modules.morphia.Blob;
import play.mvc.Controller;

import java.io.File;
import java.util.Arrays;
import java.util.List;

public class Application extends Controller {

public static void index() {
List<Album> albums = Album.findAll();
render(albums);
}

public static void album(String albumId) {
Album album = Album.findById(albumId);
notFoundIfNull(album);

render(album);
}

public static void albumForm(String albumId) {
Album album;
if (null != albumId) {
album = Album.findById(albumId);
notFoundIfNull(album);
} else {
album = new Album();
}
render(album);
}

public static void saveAlbum(Album album) {
album.save();
album(album.getIdAsStr());
}

private static String photoCacheKey() {
return session.getId() + ":photo";
}

public static void newPhotoForm(String albumId) {
Album album = Album.findById(albumId);
notFoundIfNull(album);

Photo photo = new Photo(albumId);
Cache.set(photoCacheKey(), photo);
render(album);
}

public static void deletePhoto(String photoId) {
Photo photo = Photo.findById(photoId);
notFoundIfNull(photo);
photo.delete();
album(photo.albumId);
}

public static void upload(File file) {
Photo photo = Cache.get(photoCacheKey(), Photo.class);
notFoundIfNull(photo);

photo.blob = new Blob(file);
}

public static void savePhoto(String desc, String tags) {
Photo photo = Cache.get(photoCacheKey(), Photo.class);
notFoundIfNull(photo);

photo.desc = desc;
if (null != tags) {
photo.tags.addAll(Arrays.asList(tags.split("[,; ]+")));
}
photo.save();

Cache.delete(photoCacheKey());

album(photo.albumId);
}

}
37 changes: 37 additions & 0 deletions samples-and-tests/album/app/models/Album.java
@@ -0,0 +1,37 @@
package models;

import com.google.code.morphia.annotations.Entity;
import play.modules.morphia.Model;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
* Created with IntelliJ IDEA.
* User: luog
* Date: 11/06/13
* Time: 9:18 PM
* To change this template use File | Settings | File Templates.
*/
@Entity("albumn")
public class Album extends Model {
public String name;
public Set<String> tags;

public Album() {
init();
}

public List<Photo> getPhotos() {
return Photo.find("albumId", this.getId()).asList();
}

@Model.Loaded
void init() {
if (null == tags) {
tags = new HashSet<String>();
}
}

}
42 changes: 42 additions & 0 deletions samples-and-tests/album/app/models/Photo.java
@@ -0,0 +1,42 @@
package models;

import com.google.code.morphia.annotations.Entity;
import play.modules.morphia.Blob;
import play.modules.morphia.Model;

import java.util.HashSet;
import java.util.Set;

/**
* Created with IntelliJ IDEA.
* User: luog
* Date: 11/06/13
* Time: 9:19 PM
* To change this template use File | Settings | File Templates.
*/
@Entity("photo")
public class Photo extends Model {
public String albumId;
public String desc;

public Blob blob;
public Set<String> tags;

public Photo(String albumId) {
init();
this.albumId = albumId;
}

@Model.Loaded
void init() {
if (null == tags) {
tags = new HashSet<String>();
}
}

public String getUrl() {
return null == blob ? null: blob.getUrl();
//return null;
}
}

34 changes: 34 additions & 0 deletions samples-and-tests/album/app/rythm/Application/album.html
@@ -0,0 +1,34 @@
@extends(main)

@args Album album

<h1>Album - @album.name</h1>

<style type="text/css">
ul.gallery {
list-style: none;
margin-left: 0;
}
</style>

<ul class="gallery">
@for(Photo photo: album.getPhotos()) {
<li class="photo">
<img src="@photo.getUrl()">
<div class="desc">
@photo.desc
</div>
<div>
<a class="btn" href="@url('deletePhoto(photo.getIdAsStr())')">Delete</a>
</div>
</li>
} else {
<li class="alert alert-info">
No photo found in this album
</li>
}
</ul>

<div>
<a class="btn" href="@url('newPhotoForm(album.getIdAsStr())')">Add photo</a>
</div>
20 changes: 20 additions & 0 deletions samples-and-tests/album/app/rythm/Application/albumForm.html
@@ -0,0 +1,20 @@
@extends(main)

@args Album album

<h1>
@if(album.isNew()){
Create new album
} else {
Edit album - @album.name
}
</h1>
<form action="@url(saveAlbum)" method="post">
<div>
<label>Name</label>
<input type="text" name="album.name" value="@album.name">
</div>
<div>
<button class="btn">Submit</button>
</div>
</form>
17 changes: 17 additions & 0 deletions samples-and-tests/album/app/rythm/Application/index.html
@@ -0,0 +1,17 @@
@extends(main)

@args List<Album> albums

<ul>
@for(albums) {
<li>
<a href="@url(album(_.getId()))">@_.name</a>
</li>
} else {
<div class="alert alert-info">There is no album created yet</div>
}
</ul>

<div>
<a href="@url(albumForm)" class="btn">Create new album</a>
</div>

0 comments on commit cab2016

Please sign in to comment.