Added: shindig/sandbox/trunk/cmis-binding/src/main/java/org/apache/shindig/extras/cmis/sample/CMISService.java URL: http://svn.apache.org/viewvc/shindig/sandbox/trunk/cmis-binding/src/main/java/org/apache/shindig/extras/cmis/sample/CMISService.java?rev=1028804&view=auto ============================================================================== --- shindig/sandbox/trunk/cmis-binding/src/main/java/org/apache/shindig/extras/cmis/sample/CMISService.java (added) +++ shindig/sandbox/trunk/cmis-binding/src/main/java/org/apache/shindig/extras/cmis/sample/CMISService.java Fri Oct 29 15:34:40 2010 @@ -0,0 +1,356 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.shindig.extras.cmis.sample; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Future; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.chemistry.opencmis.client.api.Document; +import org.apache.chemistry.opencmis.client.api.Folder; +import org.apache.shindig.auth.SecurityToken; +import org.apache.shindig.common.util.ImmediateFuture; +import org.apache.shindig.extras.as.sample.ActivityStreamsJsonDbService; +import org.apache.shindig.extras.cmis.utils.CMISNotifier; +import org.apache.shindig.extras.cmis.utils.CMISUtil; +import org.apache.shindig.extras.cmis.utils.CMISWrapper; +import org.apache.shindig.protocol.ProtocolException; +import org.apache.shindig.protocol.RestfulCollection; +import org.apache.shindig.protocol.conversion.BeanConverter; +import org.apache.shindig.social.opensocial.model.Album; +import org.apache.shindig.social.opensocial.model.MediaItem; +import org.apache.shindig.social.opensocial.spi.AlbumService; +import org.apache.shindig.social.opensocial.spi.CollectionOptions; +import org.apache.shindig.social.opensocial.spi.GroupId; +import org.apache.shindig.social.opensocial.spi.MediaItemService; +import org.apache.shindig.social.opensocial.spi.UserId; +import org.apache.shindig.social.sample.spi.JsonDbOpensocialService; +import org.json.JSONException; +import org.json.JSONObject; + +import com.google.common.collect.Lists; +import com.google.inject.Inject; +import com.google.inject.name.Named; + +/* + * Albums & MediaItems binding to a CMIS repository rather than the JSON DB. + * + * TODO: Currently user agnostic; implement user comparisons. + * TODO: rather than returning null, throw errors + */ +public class CMISService implements AlbumService, MediaItemService { + + public static final String SERVICE_PROVIDER_ID = "ibmcmis.dnsdojo.com"; + + private BeanConverter converter; + + private CMISNotifier notifier; + + private static final String CMIS_REPO = "http://ibmcmis.dnsdojo.com:9090/p8cmis/resources/Service"; + + private final static String ROOT_PATH = "/OpenSocial"; + + private static CMISWrapper cmis = new CMISWrapper(CMIS_REPO, ROOT_PATH); + + @Inject + public CMISService(JsonDbOpensocialService jsonDb, + @Named("shindig.bean.converter.json") BeanConverter converter) { + this.converter = converter; + this.notifier = new CMISNotifier(new ActivityStreamsJsonDbService(jsonDb, converter)); + } + + public Future<MediaItem> getMediaItem(UserId userId, String appId, + String albumId, String mediaItemId, Set<String> fields, + SecurityToken token) throws ProtocolException { + try { + Folder folder = cmis.getFolder(cmis.getRootFolder(), albumId); + if (folder == null) { + throw new ProtocolException(HttpServletResponse.SC_BAD_REQUEST, + "Album ID " + albumId + " does not exist"); + } + Document document = cmis.getDocument(folder, mediaItemId); + if (document == null) { + throw new ProtocolException(HttpServletResponse.SC_BAD_REQUEST, + "MediaItem ID " + mediaItemId + " does not exist"); + } + MediaItem mediaItem = convertJson( + CMISUtil.documentToMediaItem(document), MediaItem.class); + return ImmediateFuture.newInstance(mediaItem); + } catch (JSONException je) { + throw new ProtocolException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, + je.getMessage(), je); + } + } + + public Future<RestfulCollection<MediaItem>> getMediaItems(UserId userId, + String appId, String albumId, Set<String> mediaItemIds, + Set<String> fields, CollectionOptions options, SecurityToken token) + throws ProtocolException { + try { + Folder folder = cmis.getFolder(cmis.getRootFolder(), albumId); + List<Document> documents = cmis.getDocuments(folder); + List<MediaItem> mediaItems = Lists.newArrayList(); + for (String mediaItemId : mediaItemIds) { + boolean found = false; + for (Document doc : documents) { + MediaItem mediaItem = convertJson( + CMISUtil.documentToMediaItem(doc), MediaItem.class); + if (mediaItem.getId().equals(mediaItemId) + && mediaItem.getAlbumId().equals(albumId)) { + mediaItems.add(mediaItem); + found = true; + break; + } + } + + // Error - mediaItemId not found + if (!found) { + throw new ProtocolException(HttpServletResponse.SC_BAD_REQUEST, + "MediaItem ID " + mediaItemId + " does not exist"); + } + } + return ImmediateFuture.newInstance(new RestfulCollection<MediaItem>( + mediaItems)); + } catch (JSONException je) { + throw new ProtocolException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, + je.getMessage(), je); + } + } + + public Future<RestfulCollection<MediaItem>> getMediaItems(UserId userId, + String appId, String albumId, Set<String> fields, + CollectionOptions options, SecurityToken token) throws ProtocolException { + try { + Folder folder = cmis.getFolder(cmis.getRootFolder(), albumId); + if (folder == null) { + throw new ProtocolException(HttpServletResponse.SC_BAD_REQUEST, + "Album ID " + albumId + " does not exist"); + } + List<Document> documents = cmis.getDocuments(folder); + List<MediaItem> mediaItems = Lists.newArrayList(); + for (Document doc : documents) { + mediaItems.add(convertJson(CMISUtil.documentToMediaItem(doc), + MediaItem.class)); + } + return ImmediateFuture.newInstance(new RestfulCollection<MediaItem>( + mediaItems)); + } catch (JSONException je) { + throw new ProtocolException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, + je.getMessage(), je); + } + } + + public Future<RestfulCollection<MediaItem>> getMediaItems( + Set<UserId> userIds, GroupId groupId, String appId, Set<String> fields, + CollectionOptions options, SecurityToken token) throws ProtocolException { + List<Folder> folders = cmis.getFolders(cmis.getRootFolder()); + List<MediaItem> mediaItems = Lists.newArrayList(); + try { + for (Folder folder : folders) { + List<Document> documents = cmis.getDocuments(folder); + for (Document doc : documents) { + mediaItems.add(convertJson(CMISUtil.documentToMediaItem(doc), + MediaItem.class)); + } + } + return ImmediateFuture.newInstance(new RestfulCollection<MediaItem>( + mediaItems)); + } catch (JSONException je) { + throw new ProtocolException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, + je.getMessage(), je); + } + } + + public Future<Void> deleteMediaItem(UserId userId, String appId, + String albumId, String mediaItemId, SecurityToken token) + throws ProtocolException { + Folder folder = cmis.getFolder(cmis.getRootFolder(), albumId); + if (folder == null) { + throw new ProtocolException(HttpServletResponse.SC_BAD_REQUEST, + "Album ID " + albumId + " does not exist"); + } + Document document = cmis.getDocument(folder, mediaItemId); + if (document == null) { + throw new ProtocolException(HttpServletResponse.SC_BAD_REQUEST, + "MediaItem ID " + mediaItemId + " does not exist"); + } + + // ActivityStream notification + try { + MediaItem mediaItem = convertJson(CMISUtil.documentToMediaItem(document), MediaItem.class); + notifier.spitActivityEntry(userId, token, mediaItem, "delete", "MediaItem deleted", SERVICE_PROVIDER_ID, CMIS_REPO); + } catch (JSONException e) { + e.printStackTrace(); + } + + cmis.deleteDocument(document); + return ImmediateFuture.newInstance(null); + } + + public Future<Void> createMediaItem(UserId userId, String appId, + String albumId, MediaItem mediaItem, SecurityToken token) + throws ProtocolException { + Folder folder = cmis.getFolder(cmis.getRootFolder(), albumId); + if (folder == null) { + throw new ProtocolException(HttpServletResponse.SC_BAD_REQUEST, + "Album ID " + albumId + " does not exist"); + } + Map<String, String> docProps = CMISUtil.mediaItemToDocumentProperties(mediaItem); + cmis.createDocument(folder, docProps); + + // ActivityStream notification + notifier.spitActivityEntry(userId, token, mediaItem, "post", "MediaItem created", SERVICE_PROVIDER_ID, CMIS_REPO); + return ImmediateFuture.newInstance(null); + } + + public Future<Void> updateMediaItem(UserId userId, String appId, + String albumId, String mediaItemId, MediaItem mediaItem, + SecurityToken token) throws ProtocolException { + Folder folder = cmis.getFolder(cmis.getRootFolder(), albumId); + if (folder == null) { + throw new ProtocolException(HttpServletResponse.SC_BAD_REQUEST, + "Album ID " + albumId + " does not exist"); + } + Document document = cmis.getDocument(folder, mediaItemId); + if (document == null) { + throw new ProtocolException(HttpServletResponse.SC_BAD_REQUEST, + "MediaItem ID " + mediaItemId + " does not exist"); + } + Map<String, String> docProps = CMISUtil.mediaItemToDocumentProperties(mediaItem); + cmis.updateProperties(document, docProps); + + // ActivityStream notification + notifier.spitActivityEntry(userId, token, mediaItem, "update", "MediaItem updated", SERVICE_PROVIDER_ID, CMIS_REPO); + return ImmediateFuture.newInstance(null); + } + + public Future<Album> getAlbum(UserId userId, String appId, + Set<String> fields, String albumId, SecurityToken token) + throws ProtocolException { + try { + Folder folder = cmis.getFolder(cmis.getRootFolder(), albumId); + if (folder == null) { + throw new ProtocolException(HttpServletResponse.SC_BAD_REQUEST, + "Album ID " + albumId + " does not exist"); + } + return ImmediateFuture.newInstance(convertJson(CMISUtil.folderToAlbum(folder), Album.class)); + } catch (JSONException je) { + throw new ProtocolException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, + je.getMessage(), je); + } + } + + public Future<RestfulCollection<Album>> getAlbums(UserId userId, + String appId, Set<String> fields, CollectionOptions options, + Set<String> albumIds, SecurityToken token) throws ProtocolException { + List<Folder> folders = cmis.getFolders(cmis.getRootFolder()); + List<Album> albums = Lists.newArrayList(); + try { + for (String albumId : albumIds) { + boolean found = false; + for (Folder folder : folders) { + if (albumId.equals(folder.getId())) { + albums.add(convertJson(CMISUtil.folderToAlbum(folder), + Album.class)); + found = true; + break; + } + } + + // Error - albumId not found + if (!found) { + throw new ProtocolException(HttpServletResponse.SC_BAD_REQUEST, + "Album ID " + albumId + " does not exist"); + } + } + return ImmediateFuture.newInstance(new RestfulCollection<Album>(albums)); + } catch (JSONException je) { + throw new ProtocolException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, + je.getMessage(), je); + } + } + + public Future<RestfulCollection<Album>> getAlbums(Set<UserId> userIds, + GroupId groupId, String appId, Set<String> fields, + CollectionOptions options, SecurityToken token) throws ProtocolException { + List<Folder> folders = cmis.getFolders(cmis.getRootFolder()); + List<Album> albums = Lists.newArrayList(); + try { + for (Folder folder : folders) { + albums.add(convertJson(CMISUtil.folderToAlbum(folder), Album.class)); + } + return ImmediateFuture.newInstance(new RestfulCollection<Album>(albums)); + } catch (JSONException je) { + throw new ProtocolException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, + je.getMessage(), je); + } + } + + public Future<Void> deleteAlbum(UserId userId, String appId, String albumId, + SecurityToken token) throws ProtocolException { + Folder folder = cmis.getFolder(cmis.getRootFolder(), albumId); + if (folder == null) { + throw new ProtocolException(HttpServletResponse.SC_BAD_REQUEST, + "Album ID " + albumId + " does not exist"); + } + + try { + Album album = convertJson(CMISUtil.folderToAlbum(folder), Album.class); + List<String> verbs = new ArrayList<String>(); + verbs.add("delete"); + notifier.spitActivityEntry(userId, token, album, "delete", "Album deleted", SERVICE_PROVIDER_ID, CMIS_REPO); + } catch (JSONException e) { + e.printStackTrace(); + } + cmis.deleteFolder(folder); + return ImmediateFuture.newInstance(null); + } + + public Future<Void> createAlbum(UserId userId, String appId, Album album, + SecurityToken token) throws ProtocolException { + Map<String, String> folderProps = CMISUtil.albumToFolderProperties(album); + Folder folder = cmis.createFolder(cmis.getRootFolder(), folderProps); + notifier.spitActivityEntry(userId, token, album, "post", "Album created", SERVICE_PROVIDER_ID, CMIS_REPO); + if (folder != null) { // TODO: why is folder null? move AS code here once fixed + return ImmediateFuture.newInstance(null); + } + return null; // Error + } + + public Future<Void> updateAlbum(UserId userId, String appId, Album album, + String albumId, SecurityToken token) throws ProtocolException { + Folder folder = cmis.getFolder(cmis.getRootFolder(), albumId); + if (folder == null) { + throw new ProtocolException(HttpServletResponse.SC_BAD_REQUEST, + "Album ID " + albumId + " does not exist"); + } + cmis.updateProperties(folder, CMISUtil.albumToFolderProperties(album)); + notifier.spitActivityEntry(userId, token, album, "update", "Album updated", SERVICE_PROVIDER_ID, CMIS_REPO); + return ImmediateFuture.newInstance(null); + } + + private <T> T convertJson(JSONObject object, Class<T> clz) + throws JSONException { + return converter.convertToObject(object.toString(), clz); + } +}
Added: shindig/sandbox/trunk/cmis-binding/src/main/java/org/apache/shindig/extras/cmis/utils/CMISNotifier.java URL: http://svn.apache.org/viewvc/shindig/sandbox/trunk/cmis-binding/src/main/java/org/apache/shindig/extras/cmis/utils/CMISNotifier.java?rev=1028804&view=auto ============================================================================== --- shindig/sandbox/trunk/cmis-binding/src/main/java/org/apache/shindig/extras/cmis/utils/CMISNotifier.java (added) +++ shindig/sandbox/trunk/cmis-binding/src/main/java/org/apache/shindig/extras/cmis/utils/CMISNotifier.java Fri Oct 29 15:34:40 2010 @@ -0,0 +1,116 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.shindig.extras.cmis.utils; + +import org.apache.shindig.auth.SecurityToken; +import org.apache.shindig.extras.as.core.model.ActivityEntryImpl; +import org.apache.shindig.extras.as.core.model.ActivityObjectImpl; +import org.apache.shindig.extras.as.core.model.MediaLinkImpl; +import org.apache.shindig.extras.as.opensocial.model.ActivityEntry; +import org.apache.shindig.extras.as.opensocial.model.ActivityObject; +import org.apache.shindig.extras.as.opensocial.model.MediaLink; +import org.apache.shindig.extras.as.opensocial.spi.ActivityStreamService; +import org.apache.shindig.social.opensocial.model.Album; +import org.apache.shindig.social.opensocial.model.MediaItem; +import org.apache.shindig.social.opensocial.spi.UserId; + +/* + * Manages the creation and notification of ActivityStreams for the CMIS + * service. + */ +public class CMISNotifier { + + private boolean enabled; + + private ActivityStreamService service; + + public CMISNotifier(ActivityStreamService service) { + this.service = service; + this.enabled = true; + } + + public CMISNotifier(ActivityStreamService service, boolean enabled) { + this.service = service; + this.enabled = enabled; + } + + public void spitActivityEntry(UserId userId, SecurityToken token, + MediaItem mediaItem, String verb, String title, + String serviceProviderId, String serviceProviderUrl) { + if (!enabled) return; + ActivityEntry entry = new ActivityEntryImpl(); + entry.setTitle(title); + entry.setPostedTime("" + System.currentTimeMillis()); // TODO: extract, correct time format? + entry.setVerb(verb); + ActivityObject actor = new ActivityObjectImpl(); + actor.setId(userId.getUserId()); + entry.setActor(actor); // TODO: extract + ActivityObject object = new ActivityObjectImpl(); + object.setDisplayName(mediaItem.getTitle()); + object.setId(mediaItem.getId()); + object.setSummary(mediaItem.getDescription()); + object.setLink(mediaItem.getUrl()); + MediaLink mediaLink = new MediaLinkImpl(); + mediaLink.setDuration(mediaItem.getDuration()); + object.setMedia(mediaLink); + object.setObjectType("file"); + ActivityObject serviceProvider = new ActivityObjectImpl(); + serviceProvider.setId(serviceProviderId); + serviceProvider.setDisplayName(serviceProviderId); + serviceProvider.setLink(serviceProviderUrl); + entry.setProvider(serviceProvider); + entry.setObject(object); + service.createActivityEntry(userId, null, null, null, entry, token); + } + + public void spitActivityEntry(UserId userId, SecurityToken token, + Album album, String verb, String title, + String serviceProviderId, String serviceProviderUrl) { + if (!enabled) return; + ActivityObject object = new ActivityObjectImpl(); + object.setSummary(album.getDescription()); + object.setId(album.getId()); + object.setObjectType("folder"); + ActivityObject actor = new ActivityObjectImpl(); + actor.setId(userId.getUserId()); + object.setDisplayName(album.getTitle()); + ActivityObject serviceProvider = new ActivityObjectImpl(); + serviceProvider.setId(serviceProviderId); + serviceProvider.setDisplayName(serviceProviderId); + serviceProvider.setLink(serviceProviderUrl); + ActivityEntry entry = new ActivityEntryImpl(); + entry.setTitle(title); + entry.setProvider(serviceProvider); + entry.setObject(object); + entry.setActor(actor); + entry.setVerb(verb); + service.createActivityEntry(userId, null, null, null, entry, token); + } + public ActivityStreamService getService() { + return this.service; + } + + public void enable() { + this.enabled = true; + } + + public void disable() { + this.enabled = false; + } +} Added: shindig/sandbox/trunk/cmis-binding/src/main/java/org/apache/shindig/extras/cmis/utils/CMISUtil.java URL: http://svn.apache.org/viewvc/shindig/sandbox/trunk/cmis-binding/src/main/java/org/apache/shindig/extras/cmis/utils/CMISUtil.java?rev=1028804&view=auto ============================================================================== --- shindig/sandbox/trunk/cmis-binding/src/main/java/org/apache/shindig/extras/cmis/utils/CMISUtil.java (added) +++ shindig/sandbox/trunk/cmis-binding/src/main/java/org/apache/shindig/extras/cmis/utils/CMISUtil.java Fri Oct 29 15:34:40 2010 @@ -0,0 +1,166 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.shindig.extras.cmis.utils; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.chemistry.opencmis.client.api.Document; +import org.apache.chemistry.opencmis.client.api.Folder; +import org.apache.chemistry.opencmis.commons.PropertyIds; +import org.apache.chemistry.opencmis.commons.enums.BaseTypeId; +import org.apache.shindig.social.opensocial.model.Album; +import org.apache.shindig.social.opensocial.model.MediaItem; +import org.json.JSONException; +import org.json.JSONObject; + +/* + * Mapping utilities for conversion between OpenSocial Albums & MediaItems and + * CMIS Folders & Documents, respectively. + */ +public class CMISUtil { + + /* + * Maps a CMIS Document to an OpenSocial MediaItem. + * + * TODO: representing time correctly? + * TODO: thumbnailUrl & URL: query, feed, or parse OR <base>/objectId/majorVersion/filename? + * + * @param doc is the Document to map to a MediaItem + * + * @return JSONObject represents the MediaItem as a JSONObject + */ + public static JSONObject documentToMediaItem(Document doc) { + try { + JSONObject mediaItem = new JSONObject(); + mediaItem.put("albumId", doc.getParents().get(0).getId()); // albumId <--> parent's ID + mediaItem.put("created", doc.getCreationDate().getTime().toString()); // created <--> creationDate + mediaItem.put("description", doc.getCheckinComment()); // description <--> checkinComment + mediaItem.put("fileSize", doc.getContentStreamLength()); // fileSize <--> contentStreamLength + mediaItem.put("id", doc.getId()); // id <--> objectId + mediaItem.put("lastUpdated", doc.getLastModificationDate().getTime().toString()); // lastUpdated <--> lastModificationDate + mediaItem.put("mimeType", doc.getContentStreamMimeType()); // mimeType <--> contentStreamMimeType + mediaItem.put("title", doc.getName()); // title <--> name + String type = getMediaType(doc.getContentStreamMimeType()); + if (type != null) mediaItem.put("type", type); // type <--> contentStreamMimeType (parsed) + // TODO: MediaItem does not have ownerId, otherwise ownerId <--> createdBy + return mediaItem; + } catch (JSONException e) { + e.printStackTrace(); + } + return null; // Error + } + + /* + * Maps a CMIS Folder to an OpenSocial Album. + * + * @param folder is the Folder to map to an Album + * + * @return JSONObject represents the Album as a JSONObject + */ + public static JSONObject folderToAlbum(Folder folder) { + try { + JSONObject album = new JSONObject(); + album.put(Album.Field.TITLE.toString(), folder.getName()); + album.put(Album.Field.ID.toString(), folder.getId()); + return album; + } catch (JSONException e) { + e.printStackTrace(); + } + return null; + } + + /* + * Maps a MediaItem to properties that define a CMIS Document. + * + * @param mediaItem is the MediaItem to map to CMIS Document properties + * + * @return Map<String, String> are the properties defining a CMIS Document + */ + public static Map<String, String> mediaItemToDocumentProperties(MediaItem mediaItem) { + // Compose properties associated with document + Map<String, String> properties = new HashMap<String, String>(); + properties.put(PropertyIds.OBJECT_TYPE_ID, BaseTypeId.CMIS_DOCUMENT.value()); + put(properties, PropertyIds.CREATION_DATE, mediaItem.getCreated()); + put(properties, PropertyIds.CHECKIN_COMMENT, mediaItem.getDescription()); + put(properties, PropertyIds.CONTENT_STREAM_LENGTH, mediaItem.getFileSize()); + put(properties, PropertyIds.OBJECT_ID, mediaItem.getId()); + put(properties, PropertyIds.LAST_MODIFICATION_DATE, mediaItem.getLastUpdated()); + put(properties, PropertyIds.CONTENT_STREAM_MIME_TYPE, mediaItem.getMimeType()); + put(properties, PropertyIds.NAME, mediaItem.getTitle()); + put(properties, PropertyIds.CONTENT_STREAM_ID, mediaItem.getUrl()); + return properties; + } + + /* + * Maps an Album to properties that define a CMIS Folder. + * + * @param album is the Album to map to CMIS Folder properties + * + * @return Map<String, String> are the properties that define a CMIS Folder + */ + public static Map<String, String> albumToFolderProperties(Album album) { + Map<String, String> properties = new HashMap<String, String>(); + properties.put(PropertyIds.OBJECT_TYPE_ID, BaseTypeId.CMIS_FOLDER.value()); + put(properties, PropertyIds.NAME, album.getTitle()); + put(properties, PropertyIds.OBJECT_ID, album.getId()); + return properties; + } + + //---------------------------- PRIVATE HELPERS ---------------------------- + + /* + * Puts the given value to the given property if value is non-null and + * non-empty. + * + * @param map is the map to put the value into + * @param prop is the property to put the value to + * @param value is the value to put for the property + * + * @return true if the value was put, false otherwise + */ + private static boolean put(Map<String, String> map, String prop, String value) { + if (value != null && !value.isEmpty()) { + map.put(prop, value); + return true; + } + return false; + } + + /* + * Translates a MIME type into a MediaItem type. + * + * @param mimeType is the MIME type to translate + * + * @return a String representing a MediaItem type + */ + private static String getMediaType(String mimeType) { + if (mimeType == null) { + return null; + } else if (mimeType.contains("audio")) { + return MediaItem.Type.AUDIO.toString(); + } else if (mimeType.contains("video")) { + return MediaItem.Type.VIDEO.toString(); + } else if (mimeType.contains("image")) { + return MediaItem.Type.IMAGE.toString(); + } else { + return null; + } + } +} Added: shindig/sandbox/trunk/cmis-binding/src/main/java/org/apache/shindig/extras/cmis/utils/CMISWrapper.java URL: http://svn.apache.org/viewvc/shindig/sandbox/trunk/cmis-binding/src/main/java/org/apache/shindig/extras/cmis/utils/CMISWrapper.java?rev=1028804&view=auto ============================================================================== --- shindig/sandbox/trunk/cmis-binding/src/main/java/org/apache/shindig/extras/cmis/utils/CMISWrapper.java (added) +++ shindig/sandbox/trunk/cmis-binding/src/main/java/org/apache/shindig/extras/cmis/utils/CMISWrapper.java Fri Oct 29 15:34:40 2010 @@ -0,0 +1,186 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.shindig.extras.cmis.utils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.chemistry.opencmis.client.api.CmisObject; +import org.apache.chemistry.opencmis.client.api.Document; +import org.apache.chemistry.opencmis.client.api.Folder; +import org.apache.chemistry.opencmis.client.api.Repository; +import org.apache.chemistry.opencmis.client.api.Session; +import org.apache.chemistry.opencmis.client.api.SessionFactory; +import org.apache.chemistry.opencmis.client.runtime.SessionFactoryImpl; +import org.apache.chemistry.opencmis.commons.SessionParameter; +import org.apache.chemistry.opencmis.commons.enums.BaseTypeId; +import org.apache.chemistry.opencmis.commons.enums.BindingType; +import org.apache.chemistry.opencmis.commons.enums.UnfileObject; +import org.apache.chemistry.opencmis.commons.exceptions.CmisConnectionException; +import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException; + +/* + * Wraps high-level interaction with a CMIS repository. + */ +public class CMISWrapper { + + private Session session; + private Folder root; + private String repo; + private String rootPath; + + /* + * Constructs the CMIS wrapper with the given repository. + * + * @param cmisRepo references the repository to connect + */ + public CMISWrapper(String cmisRepo, String rootPath) { + this.repo = cmisRepo; + this.rootPath = rootPath; + this.session = newSession(); + this.root = getRoot(); + } + + public Folder getRootFolder() { + return root; + } + + public List<Folder> getFolders(Folder parent) { + List<Folder> folders = new ArrayList<Folder>(); + Iterator<CmisObject> children = parent.getChildren().iterator(); + while (children.hasNext()) { + CmisObject child = children.next(); + if (child.getBaseTypeId() == BaseTypeId.CMIS_FOLDER) { + folders.add((Folder)child); + } + } + return folders; + } + + public Folder getFolder(Folder parent, String id) { + List<Folder> folders = getFolders(parent); + for (Folder folder : folders) { + if (folder.getId().equals(id)) { + return folder; + } + } + return null; + } + + public List<Document> getDocuments(Folder parent) { + List<Document> docs = new ArrayList<Document>(); + Iterator<CmisObject> children = parent.getChildren().iterator(); + while (children.hasNext()) { + CmisObject child = children.next(); + if (child.getBaseTypeId() == BaseTypeId.CMIS_DOCUMENT) { + docs.add((Document)child); + } + } + return docs; + } + + public Document getDocument(Folder parent, String id) { + List<Document> documents = getDocuments(parent); + for (Document document : documents) { + if (document.getId().equals(id)) { + return document; + } + } + return null; + } + + public Document createDocument(Folder parent, Map<String, String> properties) { + return parent.createDocument(properties, null, null, null, null, null, null); + } + + public Folder createFolder(Folder parent, Map<String, String> properties) { + return parent.createFolder(properties, null, null, null, null); + } + + public void deleteDocument(Document doc) { + doc.delete(true); + } + + public void deleteFolder(Folder folder) { + folder.deleteTree(true, UnfileObject.DELETE, true); + } + + public void updateProperties(CmisObject object, Map<String, String> props) { + object.updateProperties(props); + } + + public Folder getParent(Document child) { + return child.getParents().get(0); + } + + public Folder getParent(Folder child) { + return child.getParents().get(0); + } + + // ---------------------------- PRIVATE HELPERS --------------------------- + private Session newSession() { + // Default factory implementation of client runtime. + SessionFactory sessionFactory = SessionFactoryImpl.newInstance(); + Map<String, String> parameter = new HashMap<String, String>(); + + // User credentials. + //parameter.put(SessionParameter.USER, "dummyuser"); + //parameter.put(SessionParameter.PASSWORD, "dummysecret"); + + // Connection settings. + parameter.put(SessionParameter.ATOMPUB_URL, this.repo); // URL to CMIS server. + // parameter.put(SessionParameter.REPOSITORY_ID, "myRepository"); // Only necessary if there are more than one repository. + parameter.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value()); + + // Session locale. + parameter.put(SessionParameter.LOCALE_ISO3166_COUNTRY, ""); + parameter.put(SessionParameter.LOCALE_ISO639_LANGUAGE, "en"); + parameter.put(SessionParameter.LOCALE_VARIANT, "US"); + + // Create session. + Session session = null; + try { + // This supposes only one repository is available at the URL. + Repository soleRepository = sessionFactory.getRepositories(parameter).get(0); + session = soleRepository.createSession(); + } + catch(CmisConnectionException e) { + // The server is unreachable + e.printStackTrace(); + } + catch(CmisRuntimeException e) { + // The user/password have probably been rejected by the server. + e.printStackTrace(); + } + + return session; + } + + /* + * Returns the root directory for working with the CMIS repository. Note + * that this is not necessarily the real repository's root, but it's the + * root for testing functionality. + */ + private Folder getRoot() { + return (Folder)session.getObjectByPath(rootPath); + } +} Added: shindig/sandbox/trunk/cmis-binding/src/main/java/org/apache/shindig/extras/cmis/utils/RepoUtil.java URL: http://svn.apache.org/viewvc/shindig/sandbox/trunk/cmis-binding/src/main/java/org/apache/shindig/extras/cmis/utils/RepoUtil.java?rev=1028804&view=auto ============================================================================== --- shindig/sandbox/trunk/cmis-binding/src/main/java/org/apache/shindig/extras/cmis/utils/RepoUtil.java (added) +++ shindig/sandbox/trunk/cmis-binding/src/main/java/org/apache/shindig/extras/cmis/utils/RepoUtil.java Fri Oct 29 15:34:40 2010 @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.shindig.extras.cmis.utils; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.chemistry.opencmis.commons.PropertyIds; +import org.apache.chemistry.opencmis.commons.enums.BaseTypeId; + +/* + * Utility for manipulating a live CMIS repository (e.g. recreating a folder). + */ +public class RepoUtil { + + private final static String REPO = "http://ibmcmis.dnsdojo.com:9090/p8cmis/resources/Service"; + private static CMISWrapper cmisWrapper; + + public static void main(String[] args) { + cmisWrapper = new CMISWrapper(REPO, "/"); + Map<String, String> folderProps = createFolderProps("OpenSocial", null); + cmisWrapper.createFolder(cmisWrapper.getRootFolder(), folderProps); + } + + private static Map<String, String> createFolderProps(String name, String id) { + Map<String, String> properties = new HashMap<String, String>(); + properties.put(PropertyIds.OBJECT_TYPE_ID, BaseTypeId.CMIS_FOLDER.value()); + put(properties, PropertyIds.NAME, name); + put(properties, PropertyIds.OBJECT_ID, null); + return properties; + } + + // ---------------------------- PRIVATE HELPERS --------------------------- + /* + * Puts the given value to the given property if value is non-null and + * non-empty. + * + * @param map is the map to put the value into + * @param prop is the property to put the value to + * @param value is the value to put for the property + * + * @return true if the value was put, false otherwise + */ + private static boolean put(Map<String, String> map, String prop, String value) { + if (value != null && !value.isEmpty()) { + map.put(prop, value); + return true; + } + return false; + } +} Added: shindig/sandbox/trunk/cmis-binding/src/main/webapp/WEB-INF/web.xml URL: http://svn.apache.org/viewvc/shindig/sandbox/trunk/cmis-binding/src/main/webapp/WEB-INF/web.xml?rev=1028804&view=auto ============================================================================== --- shindig/sandbox/trunk/cmis-binding/src/main/webapp/WEB-INF/web.xml (added) +++ shindig/sandbox/trunk/cmis-binding/src/main/webapp/WEB-INF/web.xml Fri Oct 29 15:34:40 2010 @@ -0,0 +1,179 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> +<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="Shindig" version="2.5"> + <display-name>Shindig</display-name> + <context-param> + <param-name>guice-modules</param-name> + <param-value> + org.apache.shindig.common.PropertiesModule: + org.apache.shindig.gadgets.DefaultGuiceModule: + org.apache.shindig.social.core.config.SocialApiGuiceModule: + org.apache.shindig.extras.cmis.CMISGuiceModule: + org.apache.shindig.gadgets.oauth.OAuthModule: + org.apache.shindig.common.cache.ehcache.EhCacheModule: + org.apache.shindig.extras.ShindigExtrasGuiceModule: + org.apache.shindig.extras.as.ActivityStreamsGuiceModule: + </param-value> + </context-param> + <context-param> + <param-name>system.properties</param-name> + <param-value> + shindig.host=localhost + shindig.port=8080 + </param-value> + </context-param> + <filter> + <filter-name>authFilter</filter-name> + <filter-class>org.apache.shindig.auth.AuthenticationServletFilter</filter-class> + </filter> + <filter-mapping> + <filter-name>authFilter</filter-name> + <url-pattern>/social/*</url-pattern> + <url-pattern>/gadgets/ifr</url-pattern> + <url-pattern>/gadgets/makeRequest</url-pattern> + <url-pattern>/gadgets/api/rpc/*</url-pattern> + <url-pattern>/gadgets/api/rest/*</url-pattern> + <url-pattern>/rpc/*</url-pattern> + <url-pattern>/rest/*</url-pattern> + </filter-mapping> + <listener> + <listener-class>org.apache.shindig.common.servlet.GuiceServletContextListener</listener-class> + </listener> + <servlet> + <servlet-name>xml-to-html</servlet-name> + <servlet-class> + org.apache.shindig.gadgets.servlet.GadgetRenderingServlet + </servlet-class> + </servlet> + <servlet> + <servlet-name>accel</servlet-name> + <servlet-class> + org.apache.shindig.gadgets.servlet.HtmlAccelServlet + </servlet-class> + </servlet> + <servlet> + <servlet-name>proxy</servlet-name> + <servlet-class> + org.apache.shindig.gadgets.servlet.ProxyServlet + </servlet-class> + </servlet> + <servlet> + <servlet-name>makeRequest</servlet-name> + <servlet-class> + org.apache.shindig.gadgets.servlet.MakeRequestServlet + </servlet-class> + </servlet> + <servlet> + <servlet-name>concat</servlet-name> + <servlet-class> + org.apache.shindig.gadgets.servlet.ConcatProxyServlet + </servlet-class> + </servlet> + <servlet> + <servlet-name>oauthCallback</servlet-name> + <servlet-class> + org.apache.shindig.gadgets.servlet.OAuthCallbackServlet + </servlet-class> + </servlet> + <servlet> + <servlet-name>metadata</servlet-name> + <servlet-class> + org.apache.shindig.gadgets.servlet.RpcServlet + </servlet-class> + </servlet> + <servlet> + <servlet-name>js</servlet-name> + <servlet-class>org.apache.shindig.gadgets.servlet.JsServlet</servlet-class> + </servlet> + <servlet> + <servlet-name>restapiServlet</servlet-name> + <servlet-class> + org.apache.shindig.protocol.DataServiceServlet + </servlet-class> + <init-param> + <param-name>handlers</param-name> + <param-value>org.apache.shindig.handlers</param-value> + </init-param> + </servlet> + <servlet> + <servlet-name>jsonRpcServlet</servlet-name> + <servlet-class> + org.apache.shindig.protocol.JsonRpcServlet + </servlet-class> + <init-param> + <param-name>handlers</param-name> + <param-value>org.apache.shindig.handlers</param-value> + </init-param> + </servlet> + <servlet> + <servlet-name>sampleOAuth</servlet-name> + <servlet-class> + org.apache.shindig.social.sample.oauth.SampleOAuthServlet + </servlet-class> + </servlet> + <servlet-mapping> + <servlet-name>js</servlet-name> + <url-pattern>/gadgets/js/*</url-pattern> + </servlet-mapping> + <servlet-mapping> + <servlet-name>proxy</servlet-name> + <url-pattern>/gadgets/proxy/*</url-pattern> + </servlet-mapping> + <servlet-mapping> + <servlet-name>makeRequest</servlet-name> + <url-pattern>/gadgets/makeRequest</url-pattern> + </servlet-mapping> + <servlet-mapping> + <servlet-name>jsonRpcServlet</servlet-name> + <url-pattern>/rpc/*</url-pattern> + <url-pattern>/gadgets/api/rpc/*</url-pattern> + <url-pattern>/social/rpc/*</url-pattern> + </servlet-mapping> + <servlet-mapping> + <servlet-name>restapiServlet</servlet-name> + <url-pattern>/rest/*</url-pattern> + <url-pattern>/gadgets/api/rest/*</url-pattern> + <url-pattern>/social/rest/*</url-pattern> + </servlet-mapping> + <servlet-mapping> + <servlet-name>concat</servlet-name> + <url-pattern>/gadgets/concat</url-pattern> + </servlet-mapping> + <servlet-mapping> + <servlet-name>oauthCallback</servlet-name> + <url-pattern>/gadgets/oauthcallback</url-pattern> + </servlet-mapping> + <servlet-mapping> + <servlet-name>xml-to-html</servlet-name> + <url-pattern>/gadgets/ifr</url-pattern> + </servlet-mapping> + <servlet-mapping> + <servlet-name>accel</servlet-name> + <url-pattern>/gadgets/accel</url-pattern> + </servlet-mapping> + <servlet-mapping> + <servlet-name>metadata</servlet-name> + <url-pattern>/gadgets/metadata</url-pattern> + </servlet-mapping> + <servlet-mapping> + <servlet-name>sampleOAuth</servlet-name> + <url-pattern>/oauth/*</url-pattern> + </servlet-mapping> +</web-app> \ No newline at end of file
