/* * © Copyright IBM Corp. 2010 * * Licensed 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 com.ibm.xsp.extlib.sbt.files.type; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URLEncoder; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.faces.context.FacesContext; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.http.HttpEntity; import org.apache.http.message.BasicHttpResponse; import org.w3c.dom.Document; import com.ibm.commons.util.StringUtil; import com.ibm.commons.util.io.StreamUtil; import com.ibm.designer.runtime.util.MIME; import com.ibm.sbt.services.client.ClientService; import com.ibm.sbt.services.client.ClientService.ContentStream; import com.ibm.sbt.services.client.ClientService.HandlerJson; import com.ibm.sbt.services.client.ClientServicesException; import com.ibm.sbt.services.client.ClientService.HandlerXml; import com.ibm.sbt.services.client.connections.files.FileService; import com.ibm.sbt.services.client.connections.files.model.FileRequestParams; import com.ibm.sbt.services.client.connections.files.model.Headers; import com.ibm.sbt.services.endpoints.Endpoint; import com.ibm.sbt.services.endpoints.EndpointFactory; import com.ibm.sbt.util.DataNavigator; import com.ibm.sbt.util.XmlNavigator; import com.ibm.xsp.FacesExceptionEx; import com.ibm.xsp.extlib.beans.UserBean; import com.ibm.xsp.extlib.log.ExtlibCoreLogger; import com.ibm.xsp.extlib.sbt.files.FileEntry; import com.ibm.xsp.extlib.sbt.files.FileServiceData; import com.ibm.xsp.extlib.sbt.files.FileServiceData.FileServiceAccessor; import com.ibm.xsp.extlib.sbt.model.RestDataBlockAccessor; import com.ibm.xsp.extlib.sbt.services.client.SmartCloudService; import com.ibm.xsp.util.ManagedBeanUtil; /** * SmartCloud File type. * @author Philippe Riand * @author Justin Murray * @author doconnor */ public class SmartCloudFiles extends AbstractType { public static final String LOTUS_LIVE_SUBSCRIBER_ID = "smartCloudSubscriberId"; public static final String SERVICE_URL = "files/basic/cmis/repository"; public static final String TYPE = "smartcloud"; public SmartCloudFiles() { super(); } public void addUrlParameters(Map<String, String> map, int index, int blockSize) throws ClientServicesException { map.put("skipCount", String.valueOf(index)); map.put("maxItems", String.valueOf(blockSize)); } private void authenticate(RestDataBlockAccessor accessor) throws ClientServicesException { String endpoint = accessor.getEndpoint(); if (StringUtil.isEmpty(endpoint)) { endpoint = EndpointFactory.SERVER_SMARTCLOUD; } Endpoint ep = EndpointFactory.getEndpoint(endpoint); if (ep != null) { if (!ep.isAuthenticated()) { ep.authenticate(false); } } } protected String calculateBytes(String bytes) { Double x = Double.parseDouble(bytes); DecimalFormat oneDigit = new DecimalFormat("#,##0.0"); // Conversion to GB if (x > 1073741824) { x = x / 1073741824; return oneDigit.format(x) + " GB"; } // Conversion to MB if (x > 1048576) { x = (x / 1048576); return oneDigit.format(x) + " MB"; } // Conversion to KB if (x > 768) { x = x / 1024; return oneDigit.format(x) + " KB"; } return bytes + " bytes"; } private String composeRepositoryID(FileEntry entry) { return "p!" + entry.getUserId(); } public ClientService createClientService(Endpoint endpoint, String url) throws ClientServicesException { if(StringUtil.isEmpty(url)){ url = "files/basic/cmis/repository"; } SmartCloudService svc = new SmartCloudService(endpoint); return svc; } /* * (non-Javadoc) * * @see * com.ibm.xsp.extlib.sbt.files.IFileType#createFolder(com.ibm.xsp.extlib.security.authorization.AuthorizationBean, * java.lang.String) */ public void createFolder(Endpoint authBean, String folderName) { // Folders not implemented in SmartCLoudFiles } /* * (non-Javadoc) * * @see com.ibm.xsp.extlib.sbt.files.IFileType#deleteRow(com.ibm.xsp.extlib.sbt.files.FileServiceData.Accessor, * com.ibm.xsp.extlib.security.authorization.AuthorizationBean, java.lang.String) */ public void deleteRow(FileServiceAccessor accessor, Endpoint authBean, String rowId) { String deleteURL = accessor.getServiceUrl() + "/" + getRepositoryID() + "/object/snx:file!" + rowId; try { authenticate(accessor); ClientService svc = createClientService(authBean, deleteURL); svc.delete(deleteURL); } catch (ClientServicesException e) { throw new FacesExceptionEx(e); } } /* * (non-Javadoc) * * @see com.ibm.xsp.extlib.sbt.files.type.AbstractType#getEndpoint() */ @Override public String getDefaultEndpoint() { return EndpointFactory.getEndpointName(EndpointFactory.SERVER_SMARTCLOUD); } protected String getRepositoryID() { String subId = (String) UserBean.get().getPerson().getField(LOTUS_LIVE_SUBSCRIBER_ID); if(StringUtil.isEmpty(subId)){ if(ExtlibCoreLogger.SBT.isErrorEnabled()){ ExtlibCoreLogger.SBT.errorp(this, "getRepositoryID", "SmartCloud subscriber ID is null. Repository IDs will not be resolved. Ensure that the \"extlib.people.provider\" property has been set in the application's xsp.properties (e.g. \nextlib.people.provider=smartcloud\nor some variation of this must be set in xsp.properties)"); } } subId = "p!" + subId; return subId; } /* * (non-Javadoc) * * @see com.ibm.xsp.extlib.sbt.files.IFileType#getType() */ public String getType() { return TYPE; } public List<FileEntry> readFileEntries(ClientService svc, RestDataBlockAccessor accessor, Map<String, String> params,String serviceUrl) throws ClientServicesException { authenticate(accessor); HandlerXml xml = new HandlerXml(); Document document = (Document) svc.get("files/basic/cmis/repository",params,xml).getData(); ArrayList<FileEntry> entries = new ArrayList<FileEntry>(); // Extract the content from the ATOM feed... XmlNavigator navigator = new XmlNavigator(document); //TODO Externalize these constants DataNavigator mynav = navigator.get("feed/entry"); if (mynav != null) { String epName = accessor.findEndpointName(); for (int i = 0; i < mynav.getCount(); i++) { FileEntry entry = new FileEntry(); DataNavigator nav = mynav.get(i); entry.setUserId((String) UserBean.get().getPerson().getField(LOTUS_LIVE_SUBSCRIBER_ID)); entry.setTitle(nav.stringValue("title")); entry.setUpdated(nav.dateValue("updated")); entry.setPublished(nav.dateValue("published")); entry.setAuthorName(nav.stringValue("author/name")); String id = nav.stringValue("id"); if (StringUtil.isNotEmpty(id)) { int index = id.indexOf("snx:file!"); if (index != -1) { index = index + "snx:file!".length(); id = id.substring(index); } } //hack id=id.replace("http://www.ibm.com/xmlns/prod/sn/cmis/00000000-0000-0000-0001-000000000000!", ""); entry.setFileId(id); entry.setUniqueId(id); DataNavigator propsNavigator = nav.get("object/properties"); String description = propsNavigator.get("propertyString").selectEq("@displayName", "Description").stringValue("value"); entry.setDescription(StringUtil.getNonNullString(description)); String size = propsNavigator.get("propertyInteger").selectEq("@propertyDefinitionId", "cmis:contentStreamLength").stringValue("value"); entry.setSize(calculateBytes(size)); String version = propsNavigator.get("propertyString").selectEq("@propertyDefinitionId", "cmis:versionLabel").stringValue("value"); entry.setVersion(StringUtil.getNonNullString(version)); String visibility = propsNavigator.get("propertyString").selectEq("@propertyDefinitionId", "snx:visibilityComputed").stringValue("value"); entry.setVisibility(StringUtil.getNonNullString(visibility)); String mimeType = propsNavigator.get("propertyString").selectEq("@propertyDefinitionId", "cmis:contentStreamMimeType").stringValue("value"); entry.setMimeType(mimeType); entry.setIcon(MimeIconRegistry.getInstance().get(mimeType)); String proxyUrl = "xsp/.proxy/files/" + entry.getTitle() + "?" + PARAM_TYPE + "=" + TYPE + "&" + PARAM_ID + "=" + entry.getFileId() + "&" + PARAM_REPOSITORY_ID + "=" + composeRepositoryID(entry) + "&"+"fileName="+entry.getTitle()+ "&" + PARAM_ENDPOINT_NAME + "="; if (StringUtil.isNotEmpty(epName)) { proxyUrl = proxyUrl + epName; } else { proxyUrl = proxyUrl + TYPE; } entry.setProxyURL(proxyUrl); entries.add(entry); } } return entries; } @Override public void serviceProxy(HttpServletRequest request, HttpServletResponse servletResponse) throws ServletException, IOException { try { String endpoint = request.getParameter(PARAM_ENDPOINT_NAME); if (StringUtil.isEmpty(endpoint)) { endpoint = TYPE; } Endpoint bean = (Endpoint) ManagedBeanUtil.getBean(FacesContext.getCurrentInstance(), endpoint); if (bean == null) { throw new ServletException("AuthorizationBean not found"); } if (!bean.isAuthenticated()) { bean.authenticate(false); } String fileId = request.getParameter(PARAM_ID); String repositoryId = request.getParameter(PARAM_REPOSITORY_ID); String href = "/" + repositoryId + "/object/snx:file!" + fileId + "/stream/" + fileId; SmartCloudService svc = (SmartCloudService) createClientService(bean, href); Object file; try { file = svc.get("files/basic/cmis/repository/"+href).getData(); } catch (ClientServicesException e) { throw new FacesExceptionEx(e, "Failed to perform proxy request"); } String nameUTF8 = URLEncoder.encode(request.getParameter("fileName"),"utf-8");//$NON-NLS-1$ nameUTF8 = nameUTF8.replaceAll("\\+", "%20");//$NON-NLS-1$ //$NON-NLS-2$ String userAgent= request.getHeader("User-Agent"); //$NON-NLS-1$ if(StringUtil.isNotEmpty(userAgent) && userAgent.contains("Firefox")) //$NON-NLS-1$ //use the format of value of non-acsii charset: filename*="utf8''nameUTF8" servletResponse.setHeader("Content-Disposition","attachment; filename*=\"utf8\'\'"+nameUTF8+'"');//$NON-NLS-1$ $NON-NLS-2$ $NON-NLS-3$ else servletResponse.setHeader("Content-Disposition","attachment; filename="+nameUTF8+"");//$NON-NLS-1$ $NON-NLS-2$ $NON-NLS-3$ OutputStream out = servletResponse.getOutputStream(); try{ StreamUtil.copyStream((InputStream) file, out); } finally{ out.close(); } } catch (Exception e) { throw new ServletException(e); } } /* * (non-Javadoc) * * @see com.ibm.xsp.extlib.sbt.files.IFileType#uploadFile(com.ibm.xsp.extlib.services.client.Endpoint, java.io.File, * java.util.HashMap) */ public void uploadFile(Endpoint authBean, File serverFile, FileServiceData dataSource, HashMap<String, String> params) throws CloneNotSupportedException { String name = params.get("file"); try { int dot = name.lastIndexOf('.'); String ext = null; if (dot > -1) { ext = name.substring(dot + 1); // add one for the dot! } if (StringUtil.isEmpty(ext)) { throw new FacesExceptionEx(new NullPointerException(), "Extension of file being uploaded may not be null"); } if (authBean != null && !authBean.isAuthenticated()) { authBean.authenticate(false); } InputStream is = null; try { is = new FileInputStream(serverFile); ContentStream contentFile = new ContentStream(is,serverFile.length(), name); SmartCloudService svc = new SmartCloudService(authBean); svc.post(SERVICE_URL, params, contentFile); } catch (ClientServicesException e) { e.printStackTrace(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { if(is != null) try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } catch (ClientServicesException e) { throw new FacesExceptionEx(e); } } /* * (non-Javadoc) * * @see com.ibm.xsp.extlib.sbt.files.IFileType#useFolders() */ public boolean useFolders() { return false; } }